Creating Bookings
You drive a guest's whole access lifecycle — grant on booking, revoke on cancel/checkout — by sending booking events to Mosler Direct. One endpoint handles create, update, and cancel; the action field says which.
Events are processed asynchronously: Mosler accepts your event with 202 Accepted and an eventId, then provisions device access in the background. You can poll the event to confirm completion.
v3 → v4 difference: v3 used synchronous REST —
POST /api/v3/bookingreturned the created booking directly. v4 is fully asynchronous: the202response only confirms the event was accepted; you must poll theeventIdor wait for a push notification to know when access is ready. Thereference_idyou choose replaces v3's internal booking IDs as the key used across the entire lifecycle — create, update, cancel, and credential retrieval all key off this same value.
Endpoint
POST https://webhook.mosler.in/webhook/t/<your-token>
The token in the URL encodes your company, site, and provider — no other auth is needed. Prefer not to put the credential in the URL? Use the header alternative: POST /webhook/generic with apikey, X-Company-Id, and X-Site-Id.
| Header | Type | Required | Description |
|---|---|---|---|
Content-Type | string | Yes | application/json |
X-Correlation-Id | string | No | Your own trace ID, echoed in Mosler logs |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
reference_id | string | Yes | Your booking identifier. Used for idempotency and to match follow-up events (update, cancel). Reuse the same value across a booking's lifecycle. |
action | string | Yes | Lifecycle action — see mapping. |
room / room_number | string | Conditionally | Room name as it appears in the Location API. Required for create / update / checkin / checkout; optional for cancel. |
bed / bed_number | string | No | Bed name within the room, for shared/dormitory properties. |
room_id / bed_id | string | No | (Planned) Your own location ID, if you've attached external IDs. Resolved before name matching — rename-proof. |
check_in / start_date | string | Yes | Check-in date/time. ISO 8601 preferred. |
check_out / end_date | string | Yes | Check-out date/time. |
guest.name | string | No | Guest full name. |
guest.email | string | No | Guest email. Provide email or phone (both recommended). |
guest.phone | string | No | Guest phone with country code, e.g. +919991234567. |
access_type | string | string[] | No | Credential type(s) to provision. Default: EKEY. See access types. |
card_id | string | No | RFID card identifier — required when access_type includes CARD. |
Guest contact drives delivery. If you want Mosler to send the credential straight to the guest (see Delivering Access), include
guest.phoneand/orguest.email.
Action mapping
The action string is normalised — casing and separators (_, -) are ignored.
| Your action string | Maps to |
|---|---|
create, new, reservation | BOOKING_CREATE |
cancel | BOOKING_CANCEL |
checkin, check_in, check-in | BOOKING_CHECKIN |
checkout, check_out, check-out | BOOKING_CHECKOUT |
roommove, room_move, roomchange | BOOKING_ROOMMOVE |
datechange, date_change, extend | BOOKING_DATECHANGE |
| anything else | BOOKING_UPDATE |
Create a booking
curl -X POST https://webhook.mosler.in/webhook/t/<your-token> \
-H "Content-Type: application/json" \
-d '{
"reference_id": "RES-20250718-001",
"action": "create",
"room_number": "101",
"check_in": "2025-07-18T14:00:00.000Z",
"check_out": "2025-07-22T11:00:00.000Z",
"guest": {
"name": "Jane Smith",
"email": "jane.smith@example.com",
"phone": "+919991234567"
},
"access_type": "EKEY"
}'
Success — 202 Accepted
The event is validated, stored, and queued. Provisioning happens asynchronously.
{
"success": true,
"eventId": "a3f9d2e1-84c7-4b56-9f13-0d2e4c8a1b7f",
"status": "QUEUED",
"message": "Event received and queued for processing"
}
Save the eventId.
Validation error — 400 Bad Request
{
"success": false,
"errors": [
"reference_id is required",
"check_in or start_date is required"
],
"message": "Invalid payload"
}
Duplicate — 202 (idempotent)
If the same reference_id and action arrive within 60 seconds, Mosler returns the original event instead of processing it twice.
{
"success": true,
"eventId": "a3f9d2e1-84c7-4b56-9f13-0d2e4c8a1b7f",
"status": "QUEUED",
"message": "Duplicate event detected, returning existing event"
}
Update or cancel
Send the same reference_id with a different action. For a cancel, room and date fields are optional — Mosler looks up the booking by reference_id and revokes its access.
curl -X POST https://webhook.mosler.in/webhook/t/<your-token> \
-H "Content-Type: application/json" \
-d '{ "reference_id": "RES-20250718-001", "action": "cancel" }'
To change dates or room, send action: "update" (or a date-change/room-move action) with the new values and the original reference_id.
Tracking an event
Provisioning is asynchronous. Poll the event by its eventId to confirm it reached COMPLETED. In production, wait ~5 seconds before the first check.
curl https://webhook.mosler.in/webhook/events/a3f9d2e1-84c7-4b56-9f13-0d2e4c8a1b7f \
-H "apikey: YOUR_MOSLER_API_KEY"
{
"success": true,
"eventId": "a3f9d2e1-84c7-4b56-9f13-0d2e4c8a1b7f",
"status": "COMPLETED",
"message": null
}
To see every event for a booking (create, cancel, …) use GET /webhook/events/reference/:referenceId. Full status semantics, retries, and the dead-letter flow are documented in Event Lifecycle.
Once status is COMPLETED, the credential exists. Fetch it via Retrieving Access, or let Mosler push it for you — see Delivering Access.
Common errors
| Error | Likely cause |
|---|---|
reference_id is required | Missing reference_id in body |
room or room_number is required for this action | Missing room on a create/update/checkin/checkout |
status: FAILED, message Room not found | Room name doesn't match any room in the site — re-sync via the Location API |
status: FAILED, message Site not found | Token/site mismatch — the booking's site isn't configured for this company |