Mapping Locations
Mosler keeps a replica of your property's physical layout — every Site, Building, Floor, Room and Bed, with smart locks bound to rooms and beds. Before you create bookings, you map your system's rooms to Mosler's room references. After that, each booking event just names a room (and optionally a bed) and Mosler resolves the rest.
This page covers the Location API: a read-only, paginated view of your hierarchy. Use it once during onboarding to build your room mapping, and again whenever rooms are added or renamed.
Why mapping matters
When you create a booking you send a room_number (and, for shared rooms, a bed_number). Mosler matches that string against the Room (or Bed) name in its replica and provisions access on the lock(s) bound there. If the string doesn't match a room in the booking's site, the event fails with Room not found. The Location API is how you discover the exact names to send.
Endpoints
All endpoints are GET, authenticate with the apikey header, and are scoped to your company.
| Endpoint | Returns |
|---|---|
GET /api/v4/location/all | The full hierarchy, one flattened row per Site → Bed path |
GET /api/v4/location/sites | Sites only |
GET /api/v4/location/buildings | Buildings (optionally filtered by site) |
GET /api/v4/location/floors | Floors |
GET /api/v4/location/rooms | Rooms |
GET /api/v4/location/beds | Beds |
v3 → v4: These endpoints are unchanged in behaviour — they are the same underlying controller, now served under the
/api/v4/location/...prefix. Existing code calling/api/v4/location/...continues to work; migrate the prefix at your own pace.
When to use /all vs drilling down
- Use
/allfor onboarding or a full re-sync — it returns the complete Site → Building → Floor → Room → Bed path in each row, so you can build your whole mapping table in one pass. - Use the per-level endpoints when you only need part of the tree (e.g. just the room list for one site) or when you want to render a drill-down UI.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
apikey | string | Yes | Your company-scoped Mosler API key |
Content-Type | string | No | application/json |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number (default: 1) |
limit | number | No | Rows per page (default: 100, max: 100) |
GET /api/v4/location/all
Returns every location path with pagination metadata.
Request
curl https://api.mosler.in/api/v4/location/all?page=1&limit=100 \
-H "apikey: YOUR_MOSLER_API_KEY"
Response
{
"message": "Locations retrieved successfully",
"code": 7010,
"error": false,
"data": {
"locations": [
{
"site": { "name": "Delhi", "_id": "6530f9dce0c1bd73ded0d1be" },
"building": {
"name": "Main Tower",
"_id": "6530f9dce0c1bd73ded0d1bf"
},
"floor": {
"name": "First Floor",
"_id": "6530f9dce0c1bd73ded0d1c0"
},
"room": { "name": "101", "_id": "6530f9dce0c1bd73ded0d1c1" },
"bed": { "name": "Bed 1", "_id": "6530f9dce0c1bd73ded0d1c2" }
}
],
"pagination": {
"currentPage": 1,
"totalPages": 1,
"hasNext": false,
"hasPrevious": false
},
"total": 1
}
}
Data object
| Field | Type | Description |
|---|---|---|
locations | array | One row per Site → Bed path. Each level is { name, _id } |
pagination | object | currentPage, totalPages, hasNext, hasPrevious |
total | number | Total rows available across all pages |
For door-only properties (no shared beds), the bed field is absent — the booking is keyed by room alone.
Mapping the result to your booking payload
The value you care about is room.name (and bed.name for shared rooms). That is exactly the string you send as room_number (and bed_number) when creating a booking:
// From the Location API
const room = { name: "101", _id: "6530f9dce0c1bd73ded0d1c1" };
// In your booking payload
{
reference_id: "RES-20250718-001",
action: "create",
room_number: room.name, // "101"
// ...
}
Store the mapping your-room-id → Mosler room.name in your own system. You don't need Mosler's _id values to create bookings — the human-readable name within the booking's site is enough.
Keeping the mapping fresh
Re-run GET /api/v4/location/all whenever rooms are added, removed, or renamed in Mosler. If a booking ever fails with Room not found, the room reference you sent no longer matches the replica — re-sync and retry.
Attach your own IDs
Status: Planned (v4). The endpoints below describe the upcoming external-ID feature. Until they ship, bookings are matched by room name as described above.
Name-based matching breaks silently when a room is renamed in either system. To make the mapping rename-proof, you will be able to attach your own identifier (external_id) to every location level — site, building, floor, room, and bed — and then create bookings using that ID instead of the room name.
Set an ID on one location
curl -X PATCH https://api.mosler.in/api/v4/location/rooms/6530f9dce0c1bd73ded0d1c1 \
-H "apikey: YOUR_MOSLER_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "external_id": "your-room-uuid-101" }'
Send "external_id": null to clear a mapping. IDs must be unique per level within your company — a conflict returns 409 with the Mosler _id that already holds the ID.
Bulk upsert (onboarding)
Map a whole property in one call instead of one request per room:
curl -X PUT https://api.mosler.in/api/v4/location/external-ids \
-H "apikey: YOUR_MOSLER_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{ "level": "room", "id": "6530f9dce0c1bd73ded0d1c1", "external_id": "your-room-uuid-101" },
{ "level": "room", "id": "6530f9dce0c1bd73ded0d1c4", "external_id": "your-room-uuid-102" },
{ "level": "bed", "id": "6530f9dce0c1bd73ded0d1c2", "external_id": "your-bed-uuid-101a" }
]'
The response reports success or conflict per row. Once set, external_id is returned on every level in all GET /api/v4/location/* responses.
Using your IDs in bookings
With IDs attached, send room_id (and bed_id for shared rooms) in the booking payload instead of room_number. Mosler resolves the external ID before falling back to name matching, so renames on either side no longer break booking events:
{
reference_id: "RES-20250718-001",
action: "create",
room_id: "your-room-uuid-101", // your ID — rename-proof
// room_number: "101" // name fallback still works
}