v4

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 on access.provisioned / access.revoked". That was wrong: access.revoked has never carried access[] — 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 your access.revoked and access.failed events. A 4xx is treated as a definitive rejection and is not retried, so those events are dead-lettered rather than redelivered. Branch on event and 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 202 now produces exactly one callback if you have one configured, whether it succeeded or not. See Delivering Access.
  • Documented failure codes. error.code on access.failed is 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 as access.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.provisioned is no longer sent with an empty access[]. An event promising a credential and carrying none now arrives as access.failed with NO_ACTIVE_CREDENTIALS instead.
  • The booking block is omitted on an access.failed raised before a booking exists (an unmapped room, or a cancel for an unknown reference). Those events are keyed by your referenceId alone. 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 handle access.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

  • lockData and lockMac on GET …/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-key is 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 / lockMac for 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.
  • site in the booking payload. On a company-level URL each event names its own property via site (alias site_id) — a Mosler site _id or your own external_id. Site names are deliberately not matched. See identifying the site.
  • building and floor in 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.
  • UNMAPPED event status. An unresolved site reference returns 202 and 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 site in the body is ignored. PMS integrations (eZee, Hotelogix) continue to require a site-level token; a company-level URL returns 400 for those providers.
  • Header auth (POST /webhook/generic) remains site-scoped — X-Site-Id is 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, and access.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 with X-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 Accepted with an eventId immediately; provisioning happens on Mosler's side. See Event Lifecycle.
  • Event lifecycle & status tracking. Every event transitions through RECEIVED → QUEUED → PROCESSING → COMPLETED (or FAILED/DEAD_LETTER/DUPLICATE), and is queryable by eventId or referenceId.
  • Automatic retries with dead-lettering. Failed events retry up to 3 times before moving to DEAD_LETTER, with a manual retry endpoint for recovery.
  • referenceId as 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 referenceId and 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 internal bookingId) to GET /api/v4/bookings/:referenceId/access/e-key (keyed by referenceId), wrapped in a standard envelope and adding lockMac alongside lockData. The lockData/lockMac field 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.