Booking Service API Changes - v1.72.0

Release: v1.72.0 Date: 2026-08-28

MetaTitle: Booking API Changes 1.72.0 - Seatmap.pro

MetaDescription: Booking API 1.72.0 refuses orphan-creating locks and sales, adds an optional cartSeatIds field, and declares 409 on every write endpoint.


Summary

Backward Compatible: YES — no endpoint, parameter or payload shape was removed or renamed New Endpoints: 0 Modified Endpoints: the v2 lock, sale, directsale, unlock and revertsale bodies gain one optional field; the v2 autologin body gains the optional responseType field; every v2 write endpoint declares 409 Removed or Deprecated: none removed; the legacy v1.0 endpoints no longer appear in the OpenAPI document

Migration Required: NO. Orphan seat prevention is off unless enabled for an organisation, and cartSeatIds is optional.


Orphan seat prevention (SEAT-1196)

When the option is enabled for an organisation, the lock and sale endpoints refuse seats whose sale or hold would leave a single unsold seat with no available neighbour. Releasing seats is never restricted.

How a refusal is reported

API Behaviour
v1 management API The refused seats are returned in the existing unsuccessful-attempts list, and the rest of the request is applied
v2 booking API The call fails with 422 Unprocessable Content, errorCode: ORPHAN_SEATS_REFUSED, identifying the refused seats

422 is used rather than 409 so a refusal is distinguishable from a transient conflict: a 409 is worth retrying, a 422 is not.

Declaring the rest of the cart

lock, sale and directsale accept an optional cartSeatIds on the request body:

{
  "sessionId": "abc123xyz",
  "seats": [{ "seatId": 1004, "state": "LOCKED" }],
  "cartSeatIds": [1001, 1002, 1003]
}

The seats in the request and the seats in cartSeatIds are judged together as one selection, so a selection that is sound as a whole is accepted while it is still being assembled one call at a time. Submit a buyer’s whole selection in a single lock call where the integration allows it, and use the field where it does not.

  • A declared selection that would itself leave a seat with no available neighbour is refused, exactly as those seats sent in one call would be.
  • Identifiers that are already locked or sold make no difference to the verdict.
  • Maximum 1000 identifiers. null entries are rejected.
  • unlock and revertsale accept the field and ignore it.

An integrator that declares a selection is expected to complete it: a seat named in cartSeatIds but never locked is not held, and can be left standing alone.

The v1 management API has no equivalent field and continues to report refused seats in its unsuccessful-attempts list.

Aisles

Seats separated by an aisle are not treated as neighbours. A row is measured against its own seat spacing, so a wider gap in the middle of a row ends the block: a seat beside an aisle is never held back by a seat on the far side of it. The service and the renderer evaluate this against a shared fixture corpus, so both sides reach the same verdict for the same row.

Configuration

Resolved per organisation, with a per-event override, both managed from the editor (SEAT-1199). A change is applied by the endpoints within seconds (SEAT-1203). The platform default is off, and the deployment-level switch is SEATMAP_ORPHANPREVENTION_ENABLED — see the Deployment Guide.

The value is carried to the renderer on the event price payload only. It is no longer repeated in the seat map payload, which is cached for much longer and could therefore state a value the endpoints had already stopped applying.


Concurrency (SEAT-1197)

A concurrent modification of the same seats or general-admission group now answers 409 Conflict instead of a generic server error.

Every write endpoint in the v2 booking and management APIs declares 409 in the OpenAPI document, so a generated client exposes it and an integration can branch on it explicitly. A 409 means the state changed underneath the request and is worth retrying.

The published error-format reference now shows the Problem Details body the API actually returns, including the errorCode and errors members.


OpenAPI coverage (SEAT-1192)

The published description gains the validation constraints already declared on the models — minimum lengths and numeric bounds — and fields carrying free-form JSON are described as free-form objects rather than as an opaque type.

Endpoints, parameters and payload shapes are unchanged. Integrators who generate clients from the specification will see these refinements in the generated models, and may find a previously untyped field now typed.


Authentication Changes

The X-API-Key and X-Organization-ID header contract is unchanged.

One-time session code on autologin (SEAT-1212)

POST /api/public/v2.0/autologin/ accepts an optional responseType field. Omitted, the response carries session tokens exactly as before. Set to "code", the response carries a single-use session code instead:

{
  "success": true,
  "code": "{sessionCode}",
  "expiresIn": 60
}

Append the code to the Editor URL as ?ssoCode={sessionCode}; the Editor exchanges it for a session automatically when it loads. A code is valid for one exchange and expires after expiresIn seconds, so request a fresh code each time the Editor is opened. Any other responseType value is rejected with 400.


Removed and Deprecated Endpoints

No endpoint was removed. The legacy v1.0 endpoints (/api/public/v1.0/...) no longer appear in the OpenAPI document; they continue to serve existing integrations unchanged. API clients regenerated from the published document will no longer include the v1.0 surface, so integrations still on v1.0 should keep their existing client definitions.