From Venue Schema to Confirmed Booking, One API Call at a Time

Go from venue schema to confirmed booking with the Booking API, one call at a time: event, prices, map, hold and sale, with the error case at each step.

An API reference lists endpoints, not the order a backend calls them in or what a failure means at each step. Here is that order, with each failure, for the Seatmap Pro Booking API v2 and booking renderer. To compare vendors first, see what to check before choosing a ticketing API.

What changed in 1.73.0

The hold step gained a second path: besides your backend locking seats (step 7), the page can open a booking session that your backend confirms after payment (step 9). The two keys also took the names Public API key and Secret API key; their values and header names stayed the same.

Nine calls, in order

  1. Keys. Your backend calls https://booking.seatmap.pro with the Secret API key in the X-API-Key header, or with a tenant token there plus X-Organization-ID; the renderer takes the Public API key. Both keys are opaque strings shown in the Editor’s Organization settings, as the setup guide describes. A disabled organization gets 402 ORGANIZATION_DISABLED.

  2. Schema. The venue is drawn in the Editor as a schema, readable through the API down to each seat. Keep the schema id for the event.

  3. Event. POST /api/private/v2.0/events/ needs a name, a start, an end date and the schema id, and returns the event id, a UUID: keep it for the selling page. A field that fails validation answers 400 with an errors list. The API reference has the request fields, and lists 403 for no access and 409 for a conflict or duplicate.

  4. Prices. Create prices on the event and assign them to seats, rows, sections or general admission areas; an unpriced seat cannot be booked. A duplicate price name on the event answers 409, and updating or deleting a price not on that event answers 404. Bulk price creates and updates apply in full or not at all.

  5. Availability. GET /api/private/v2.0/events/{id}/seats/ returns one flat record per seat, filterable by section or row and paged in stable seat id order. To poll, echo the largest last-change time back as lastUpdated unchanged: it has no time-zone offset, so do not convert it. A seat whose price is removed drops out unreported, so read in full now and then.

  6. Renderer. On the selling page, new SeatmapBookingRenderer(container, { publicKey, ... }) takes the Public API key and await renderer.loadEvent(eventId) loads the event. A failed load says why: 410 archived, 404 missing, 422 not published. onSeatSelect fires on each click on an available seat and onSeatDeselect on deselect; returning false, or a promise of false, cancels the change. See the renderer quick start.

  7. Hold. Your backend calls POST /api/private/v2.0/booking/lock?eventId={uuid} naming the seats and general admission areas, with an optional hold type, CART by default. It answers 200 with true, or false if a seat or area was taken, not on sale, unknown or short of capacity. A seat another caller holds is a false, not an error. A false does not say which seat failed, so read the seats back before you retry. Errors cover other refusals: 400 for an unknown or unsuitable hold type, and 409 SESSION_HELD for a seat a live booking session holds. Orphan seat prevention, off by default, answers 422 ORPHAN_SEATS_REFUSED to a hold that would strand a single seat; that refusal is not worth retrying. unlock releases held seats, answering false for one that is not held.

  8. Sale. After payment, sale turns held seats into sold ones, answering true or false, and revertsale returns sold seats to sale. For back-office sales, directsale sells on-sale seats in one call with no hold, answering false if one is not.

  9. Or a booking session. The page can also hold seats itself. It opens a session with POST /api/public/v2.0/session/, sending the event id and Public API key with an Idempotency-Key header, then holds with /{id}/lock and freezes the cart with /{id}/checkout. After payment your backend confirms with POST /api/private/v2.0/session/{id}/confirm, optionally storing your order reference. Confirm answers 409 SESSION_NOT_CHECKED_OUT if the cart was never checked out and 409 SEAT_CONFLICT if a held line can no longer be sold. The 1.73.0 error table lists the other session errors; how a booking session holds and releases seats covers the rest.

Lock per click or a booking session

Choose lock per click when your backend already keeps the cart: each select locks the seat through your backend, and each deselect unlocks it. Without booking sessions, your backend owns hold lifetime and releases what it no longer needs. Choose a booking session when the page should hold seats itself and your backend only confirms. An integration that never creates sessions keeps working as before and meets 409 SESSION_HELD only for a seat a live session holds.

What to plan around

The generated OpenAPI documents do not list 409 on lock, sale or direct sale, so a client built only from them will not expect SESSION_HELD: handle it by hand. The public session calls are not in them at all; the 1.73.0 page linked above is their reference.

Where to go next

Most of a round trip is reading answers: an error code, or a plain false that sends you back to the seats. The seat map API page is the product overview behind these calls; to talk through your own round trip, book a demo.

Continue reading

All posts →