Changelog
This changelog tracks notable changes to the documented Mosler integration surface — endpoints, payloads, events, and behaviour you build against. It's organised by API version; the newest changes are at the top.
Looking for the conceptual differences between major versions? Each page also calls out v3 → v4 specifics inline (for example, the e-key endpoint note in Retrieving Access).
v4.5.1 — Correction: access[] is only on access.provisioned
Fixed (documentation)
- The payload reference stated
access[]was "present onaccess.provisioned/access.revoked". That was wrong:access.revokedhas never carriedaccess[]— the credentials are gone, so there is nothing to list. Integrators who built a validator from that line rejected every revocation callback we sent them. - Added which fields arrive on which event — an explicit per-event field matrix, so this cannot be misread again.
If your endpoint validates
access[]on every callback, it is rejecting youraccess.revokedandaccess.failedevents. A4xxis treated as a definitive rejection and is not retried, so those events are dead-lettered rather than redelivered. Branch oneventand read the fields that event carries.
No behaviour changed — this corrects the documentation to match what the API has always sent.
v4.5 — A callback for every accepted event
Booking ingestion is asynchronous — the 202 Accepted only confirms we took the event, so the callback is the only place its outcome can be reported. Previously we only sent one when provisioning succeeded, which left several real outcomes indistinguishable from a failed delivery.
Added
- One callback per accepted event. Every event answered with
202now produces exactly one callback if you have one configured, whether it succeeded or not. See Delivering Access. - Documented failure codes.
error.codeonaccess.failedis machine-readable and safe to branch on, split by whether you or Mosler is the one who fixes it:LOCATION_NOT_FOUND,BOOKING_ALREADY_ENDED,BOOKING_NOT_FOUND,NO_ACTIVE_CREDENTIALS,NO_DEVICE_BOUND,GRANT_FAILED,GRANT_ERROR. Codes are append-only — treat an unrecognised one as a generic failure. - Newly reported outcomes. An unmapped room (
LOCATION_NOT_FOUND), a stay that had already ended (BOOKING_ALREADY_ENDED), and a cancel for an unknown reference (BOOKING_NOT_FOUND) previously produced no callback at all. They now arrive asaccess.failed. - Resending a create returns the existing access. A redelivered create for a booking we already hold re-emits its current credentials instead of nothing. Nothing is re-provisioned and no passcode is reissued.
Changed
access.provisionedis no longer sent with an emptyaccess[]. An event promising a credential and carrying none now arrives asaccess.failedwithNO_ACTIVE_CREDENTIALSinstead.- The
bookingblock is omitted on anaccess.failedraised before a booking exists (an unmapped room, or a cancel for an unknown reference). Those events are keyed by yourreferenceIdalone. This was always permitted by the payload contract; it is now actually used.
Compatibility: all of this is additive under
schemaVersion: 1. If you already handleaccess.failed, you will simply start receiving it in cases that were previously silent. If you ignore it, nothing breaks — but you'll keep missing outcomes you could be acting on.
v4.4 — E-key lock data on the access API
Added
lockDataandlockMaconGET …/access. E-key entries in the access list now carry their SDK material inline, so one call returns every credential for a booking regardless of type. Previously the endpoint confirmed an e-key existed but withheld the lock data, forcing a second call. See Retrieving Access.
Changed
GET …/access/e-keyis unchanged and remains available as an e-key-only view of the same values — existing integrations need no changes.- Documentation fix: the access callback has always delivered
lockData/lockMacfor e-key credentials, but the payload reference did not list them. Delivering Access now documents the e-key fields explicitly. No behaviour changed.
v4.3 — Company-level webhook URLs
Multi-property integrators no longer need one webhook URL per site.
Added
- Company-level webhook tokens. A token can now be scoped to your company instead of a single site, so one URL covers every property. See Authentication.
sitein the booking payload. On a company-level URL each event names its own property viasite(aliassite_id) — a Mosler site_idor your ownexternal_id. Site names are deliberately not matched. See identifying the site.buildingandfloorin the booking payload. Optional references (building/building_id,floor/floor_id) recorded on the event. Room resolution does not use them — rooms are already unique within a site.UNMAPPEDevent status. An unresolvedsitereference returns202and stores the event without provisioning, rather than failing the request, so an unmapped property can't cause your system to disable the webhook. The event is replayed once the site is mapped. See Event Lifecycle.
Changed
- Existing site-level token URLs are unaffected — the site stays pinned to the URL and any
sitein the body is ignored. PMS integrations (eZee, Hotelogix) continue to require a site-level token; a company-level URL returns400for those providers. - Header auth (
POST /webhook/generic) remains site-scoped —X-Site-Idis still required.
v4.2 — Integrations & access delivery
The v4.2 line makes delivery a first-class, configurable part of the platform rather than something each integrator polls for.
Added
- Integration model. Bookings now resolve to an integration that owns a location scope (site, falling back to company). Scopes are disjoint, so exactly zero or one integration owns any given booking. With no integration configured, behaviour is unchanged — this is Mosler Direct, where Mosler messages the guest directly.
- Access callbacks. Mosler can push access events to your endpoint —
access.provisioned,access.revoked, andaccess.failed— instead of you polling. See Delivering Access. - Signed callbacks. Outbound callbacks are signed with
X-Mosler-Signature(HMAC-SHA256 over the raw body) and tagged withX-Mosler-Event. Bearer, basic, and API-key auth strategies are also supported. See Security. - Secret rotation. Callback secrets can be rotated with zero downtime by validating against the previous secret during a rotation window.
- New reference docs. Quickstart, Response Codes, Security, Rate Limits, and the Mobile Key SDK guide.
Changed
- Delivery is now driven by integration configuration. Mosler Direct (guest messaging over WhatsApp/email) is the default when no integration claims a booking's scope — so existing setups keep working without changes.
v4.0 — Asynchronous pipeline
v4 reshaped how booking events are received and processed, moving from synchronous request/response to a durable, observable pipeline.
Added
- Asynchronous ingestion. Booking events return
202 Acceptedwith aneventIdimmediately; provisioning happens on Mosler's side. See Event Lifecycle. - Event lifecycle & status tracking. Every event transitions through
RECEIVED → QUEUED → PROCESSING → COMPLETED(orFAILED/DEAD_LETTER/DUPLICATE), and is queryable byeventIdorreferenceId. - Automatic retries with dead-lettering. Failed events retry up to 3 times before moving to
DEAD_LETTER, with a manual retry endpoint for recovery. referenceIdas the lifecycle key. Access is read and tracked by your reservation reference, not an internal Mosler ID.- Unified access retrieval. A single, enveloped access API covers passcodes, cards, e-keys, and remote unlock — keyed by
referenceIdand returning per-device records. - PMS integrations. Native ingestion for eZee and Hotelogix — the PMS sends its own format and Mosler translates it. See PMS Integrations.
Changed
- E-key retrieval moved from
GET /api/v3/booking/access/ekey/:bookingId(keyed by internalbookingId) toGET /api/v4/bookings/:referenceId/access/e-key(keyed byreferenceId), wrapped in a standard envelope and addinglockMacalongsidelockData. ThelockData/lockMacfield semantics are unchanged from v3.
v3 — Synchronous REST (legacy)
The v3 API remains documented under v3 for existing integrations. It uses synchronous REST calls keyed by internal IDs. New integrations should build on v4; v3 is maintained for backward compatibility only.
Versioning policy: Within a major version, additive changes (new optional fields, new endpoints, new event types) can ship without notice. Breaking changes — removed fields, changed semantics, renamed endpoints — are introduced under a new version path and announced here.