Delivering Access
Retrieving Access is the pull model — you ask Mosler for a credential when you need it. Delivery is the push model — Mosler sends the credential to you, or directly to the guest, the moment provisioning finishes. No polling required.
There are two delivery modes; you can use either or both.
Mode 1 — Webhook event caller
Configure a callback URL on your Integration in the Mosler client portal. When the worker finishes provisioning (or revoking) access, Mosler POSTs an authenticated event to that URL. Your endpoint records the credential and replies 2xx.
Booking event COMPLETED
│
▼
Mosler ──POST {signed access.provisioned}──► https://your-system/mosler/callback
◄────────────── 200 OK ──────────────
Event payload
| Field | Type | Description |
|---|---|---|
schemaVersion | number | Payload contract version, currently 1. Pin or range-check this — new optional fields may be added under the same major. |
event | string | access.provisioned, access.revoked, or access.failed |
referenceId | string | Your booking reference |
occurredAt | string | ISO 8601 UTC timestamp |
booking | object | { id, status, startDate, endDate } |
access[] | array | Same per-device shape as GET …/access — type, the credential for that type (passcode, cardId, or lockData + lockMac for e-keys), device/room/bed, validity. Present on access.provisioned / access.revoked. |
error | object | Only on access.failed: { code, message } describing why provisioning failed (e.g. gateway offline, no device bound, room mismatch). Replaces access[]. |
{
"schemaVersion": 1,
"event": "access.provisioned",
"referenceId": "RES-20250718-001",
"occurredAt": "2025-08-01T08:30:02.114Z",
"booking": {
"id": "6576fe78632cfff91c62a3c2",
"status": "active",
"startDate": "2025-08-01T08:30:00.000Z",
"endDate": "2025-08-05T05:30:00.000Z"
},
"access": [
{
"deviceName": "Room 101 Door",
"roomNumber": "101",
"bedNumber": null,
"type": "passcode",
"passcode": "482910",
"validFrom": "2025-08-01T08:30:00.000Z",
"validUntil": "2025-08-05T05:30:00.000Z"
},
{
"deviceName": "Room 101 Door",
"roomNumber": "101",
"bedNumber": null,
"type": "ekey",
"lockData": "Rz7oNSAH1No3YXRiG0j8FKB3xBjhuILrkTjWkOMw...",
"lockMac": "AA:BB:CC:DD:EE:FF",
"validFrom": "2025-08-01T08:30:00.000Z",
"validUntil": "2025-08-05T05:30:00.000Z"
}
]
}
E-key credentials arrive in full. For
type: "ekey"the callback carrieslockDataandlockMacinline — everything the Mobile Key SDK needs. You do not have to call back to the API to complete an e-key.
An access.failed event carries an error object instead of access[]:
{
"schemaVersion": 1,
"event": "access.failed",
"referenceId": "RES-20250718-001",
"occurredAt": "2025-08-01T08:30:02.114Z",
"booking": {
"id": "6576fe78632cfff91c62a3c2",
"status": "active",
"startDate": "2025-08-01T08:30:00.000Z",
"endDate": "2025-08-05T05:30:00.000Z"
},
"error": {
"code": "NO_DEVICE_BOUND",
"message": "No lock is mapped to room 101 at this site."
}
}
Verifying the signature
By default, each call carries an X-Mosler-Signature header: an HMAC-SHA256 of the raw request body, keyed with the callback secret stored on your Integration. Recompute it and compare before trusting the payload.
import crypto from 'crypto';
function isValid(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody) // the exact bytes received
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
Outbound auth options
HMAC signing is the default. On your Integration you can instead choose Bearer token, Basic auth, a custom API-key header, or none — Mosler attaches the configured credential to every callback (including the test.ping). Pick the scheme your endpoint expects when you set up the Integration in the client portal.
Delivery guarantees
- Retries: non-
2xxresponses (and timeouts) are retried with exponential backoff. After the final attempt the event is dead-lettered and surfaced for manual replay. - Idempotency: retries reuse the same payload. De-duplicate on (
referenceId,event,occurredAt) — your endpoint may receive a delivery more than once. - Ordering: not guaranteed under retries. Treat
access.revokedas authoritative over an earlieraccess.provisionedfor the same booking by comparingoccurredAt.
Verifying your endpoint before go-live
Before you take a real booking, confirm your callback URL and signature check work end-to-end. Fire a signed test.ping at your registered URL:
POST /api/v4/callbacks/test
curl -X POST https://api.mosler.in/api/v4/callbacks/test \
-H "apikey: YOUR_API_KEY"
Mosler delivers a test.ping event to your registered callback URL — authenticated with the same scheme as real events — and returns the HTTP result it observed from your endpoint:
{
"success": true,
"delivered": true,
"url": "https://your-system/mosler/callback",
"responseStatus": 200,
"authType": "hmac"
}
The test.ping body matches the standard envelope so your verifier exercises the real code path:
{
"schemaVersion": 1,
"event": "test.ping",
"occurredAt": "2025-08-01T08:30:02.114Z",
"message": "Mosler callback verification ping."
}
No booking is created. Use this to validate your endpoint and signature verification without touching a real reservation.
Mode 2 — Direct guest messaging
Let Mosler deliver the credential straight to the guest — no callback handling, no app on your side. When provisioning completes, Mosler sends the passcode (or a mobile-key link) to the guest over WhatsApp and/or email using Mosler templates.
To enable it, include guest contact details on the booking and the property's messaging preference is configured in the Mosler Admin portal:
{
reference_id: "RES-20250718-001",
action: "create",
room_number: "101",
guest: {
name: "Jane Smith",
email: "jane.smith@example.com", // → email delivery
phone: "+919991234567" // → WhatsApp/SMS delivery
},
access_type: "PASSCODE"
}
The guest receives a Mosler-branded message with their PIN (or a link to open their mobile key) and the stay window. Revocation on checkout/cancel can likewise notify the guest that access has ended.
Choosing a mode
| Webhook event caller | Direct guest messaging | |
|---|---|---|
| Who receives the credential | Your system | The guest |
| You build | A callback endpoint | Nothing — just send guest contact |
| Best when | You own the guest experience/app | You want Mosler to handle delivery |
You can combine them: receive the callback for your records and have Mosler message the guest.
Setup
Mode 1 is self-service: create an Integration in the Mosler client portal and set its callback URL, outbound auth scheme, and scope — then verify it end-to-end with POST /api/v4/callbacks/test. Mode 2 (direct guest messaging) channel preferences are configured per company/site in the Mosler Admin portal.