Every SeatLayer integration follows one invariant:
The browser holds. Your server books.
The buyer can explore inventory and temporarily reserve a selection without receiving an account secret. Only your trusted backend can turn that hold into a permanent booking.
The complete journey
Render live inventory
Your browser or mobile surface loads a published event through the buyer SDK. The event key identifies the inventory; it does not grant server booking authority.
Select and hold
The buyer chooses seats, a table, booth, or GA quantity. The SDK creates a short-lived hold and returns an opaque holdId with an expiry time.
Inspect on your server
Your backend receives the holdId and resolves it with GET /v1/events/:eventKey/holds/:holdId. The returned items—not browser-posted prices—become the order source.
Run your order and payment logic
Create or reuse your own order. Authorize or capture payment according to your payment provider and recovery model.
Book atomically
Your backend calls POST /v1/events/:eventKey/book using a secret key and your immutable order id as bookingRef.
Confirm and reconcile
The synchronous response drives the buyer journey. Realtime updates repaint open pickers, and signed webhooks reconcile downstream systems.
Buyer
│ selects
▼
SeatLayer SDK ── creates hold ──> SeatLayer inventory
│
│ sends holdId only
▼
Your server ── inspects hold ──> authoritative items and expiry
│
├── runs your order/payment rules
│
└── books with secret key + bookingRef ──> atomic success or 409 conflictWhy the split exists
Security
A browser can reserve inventory but cannot create a permanent sale. Booking authority remains in your trusted environment.
Correctness
Each event serializes inventory transitions, so two buyers cannot successfully take the same seat.
Product control
Your application owns identity, pricing rules, payment, tax, orders, refunds, and the final confirmation experience.
What each system owns
| Responsibility | Browser / SDK | Your server | SeatLayer |
|---|---|---|---|
| Display chart and live availability | Yes | No | Supplies state |
| Let a buyer select | Yes | No | Enforces availability |
| Create and restore holds | Yes | May inspect | Stores authoritative hold |
| Calculate the trusted charge | No | Yes | Supplies trusted line items |
| Process payment and orders | No | Yes | No |
| Permanently book inventory | No | Initiates | Applies atomically |
| Realtime inventory synchronization | Receives | Optional listener | Publishes |
| Signed event notification | No | Receives | Sends |
Seat lifecycle
| State | Meaning | Typical transition |
|---|---|---|
free |
Available to buyers | Initial, released, or expired |
held |
Temporarily reserved | Buyer SDK creates a hold |
booked |
Permanently sold | Your server books |
not_for_sale |
Removed from buyer inventory | Operator or inventory rule |
Holds expire automatically. Booking is all-or-nothing: if any required item cannot be booked, the request returns a conflict without partially completing the sale.
The browser handoff
const picker = new seatlayer.SeatPicker({
container: "#picker",
event: "ev_9f3a",
onCheckout: async (_, __, handoff) => {
await fetch("/api/checkout/seats", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ holdId: handoff.holdId }),
});
},
});
await picker.render();The browser sends your backend the hold id. Your backend obtains trusted labels, quantities, tiers, currency, and prices from the hold inspection endpoint.
Expected failure paths
- Hold expired: return the buyer to selection and clear stale cart state.
- Booking returned
409: treat it as a recoverable inventory conflict; do not partially confirm the order. - Payment succeeded but booking is uncertain: retry using the same
bookingRef. - Realtime connection dropped: reconnect and refresh authoritative inventory.
- Mode mismatch: use a test key with test events and a live key with live events.
Verify your understanding
Before implementation, you should be able to answer:
- Which value crosses from the browser to your server?
- Where is the secret key stored?
- Which response supplies the trusted charge?
- Which identifier makes a retry safe?
- What buyer experience follows a
409?
Continue to Authentication, then install the Buyer SDK.