SeatLayer is a composable reserved-seating layer. Your product can use only the buyer picker, or combine venue design, event inventory, checkout holds, server booking, operations, reporting, and webhooks behind your own interface.
You keep the customer relationship, product UX, accounts, payments, taxes, orders, and business rules. SeatLayer provides the seating-specific geometry and concurrency.
Choose an integration shape
Add seating to one product
Embed the picker in an existing booking or commerce flow. Your current backend receives the hold and confirms the order.
Run a multi-organiser platform
Provision one isolated workspace per organiser, store the mapping, and expose SeatLayer through your own CMS.
Build custom venue operations
Combine APIs, the embeddable Designer/control room, and webhooks with your own permissions and workflows.
The data flow stays the same in every shape:
Your CMS ──secret key──> charts, workspaces, events
Buyer page ──event key──> render, select, hold
Your checkout ──secret key──> inspect hold, book
SeatLayer ──signed webhook──> reconciliation and downstream workMap your model to SeatLayer
| Your product | SeatLayer |
|---|---|
| Venue/layout | Reusable chart |
| Performance, departure, or timed session | Event with independent inventory |
| Tenant, organiser, or customer account | Workspace |
| Cart reservation | Hold |
| Paid/confirmed order | Booking |
| Your stable resource id | externalRef |
workspaceId is the enforced isolation boundary. externalRef is an opaque reconciliation tag; never use it as authorization.
Multi-organiser provisioning
Create an isolated workspace
Create the mapping when a customer or organiser is provisioned.
curl https://api.seatlayer.io/v1/workspaces \
-X POST \
-H "Authorization: Bearer $SEATLAYER_SECRET_KEY" \
-H "Idempotency-Key: workspace-org_123" \
-H "Content-Type: application/json" \
-d '{"name":"Organiser X","externalRef":"org_123"}'Persist the returned workspace id on your organiser record.
Create or duplicate a chart
Maintain reusable master venues, then duplicate a master into the organiser workspace.
curl https://api.seatlayer.io/v1/charts/c_master_hall/duplicate \
-X POST \
-H "Authorization: Bearer $SEATLAYER_SECRET_KEY" \
-H "Idempotency-Key: org_123-main-hall" \
-H "Content-Type: application/json" \
-d '{
"name":"Organiser X — Main Hall",
"workspaceId":"ws_7e2d",
"externalRef":"venue_81"
}'A duplicate is a draft. Review it, then publish it before creating an event.
Create an event
Events inherit the chart workspace and receive independent inventory.
curl https://api.seatlayer.io/v1/events \
-X POST \
-H "Authorization: Bearer $SEATLAYER_SECRET_KEY" \
-H "Idempotency-Key: event-show_456" \
-H "Content-Type: application/json" \
-d '{
"chartId":"c_7e2d",
"name":"Spring Gala",
"externalRef":"show_456"
}'Store the returned meta.key with your event. That public event key is what the buyer embed uses.
Embed under your brand
Render the picker in your product. No account secret is sent to the browser.
const picker = new seatlayer.SeatPicker({
container: "#seat-picker",
event: seatlayerEventKey,
theme: {
accent: "#6d28d9",
accentInk: "#ffffff",
fontFamily: "Inter, system-ui, sans-serif",
},
onCheckout: (_, __, handoff) => {
beginYourCheckout({ holdId: handoff.holdId });
},
});
await picker.render();Inspect, pay, and book
Your backend resolves the hold, derives the trusted order amount, runs your payment flow, and books with your existing order id.
const hold = await seatlayerRequest(
`/v1/events/${event.seatlayerKey}/holds/${holdId}`,
);
assertWorkspaceOwnership(event, organiser);
const order = await createOrderFromTrustedItems(hold.items);
await authorizePayment(order);
const booking = await seatlayerRequest(
`/v1/events/${event.seatlayerKey}/book`,
{
method: "POST",
body: JSON.stringify({
holdId,
bookingRef: order.id,
}),
},
);One webhook, many organisers
Account-level webhook traffic can arrive at one endpoint. Route from the SeatLayer event id/key you stored, then verify its immutable workspace matches your business record.
app.post("/webhooks/seatlayer", rawBody(), async (req, res) => {
if (!verifySeatLayerSignature(req.rawBody, req.headers)) {
return res.sendStatus(401);
}
const delivery = JSON.parse(req.rawBody);
const businessEvent = await findBySeatLayerEvent(delivery.payload.eventId);
if (
!businessEvent ||
businessEvent.seatlayerWorkspaceId !== delivery.payload.workspaceId
) {
return res.sendStatus(400);
}
await enqueueForOrganiser(businessEvent.organiserId, delivery);
return res.sendStatus(200);
});White-label boundaries
You can keep your own:
- navigation, account hierarchy, roles, and permissions;
- checkout, payments, tax, refunds, and order history;
- visual theme, surrounding content, and analytics;
- venue onboarding and approval workflow; and
- customer support and operational runbooks.
SeatLayer remains responsible for:
- chart geometry and semantic seating objects;
- selection rules and accessible-seat relationships;
- realtime holds and availability;
- atomic booking transitions;
- buyer 2D/3D visualization; and
- signed event notifications.
Platform best practices
- Keep one workspace per isolation boundary, not per event.
- Reuse a chart for repeat performances; do not duplicate it for each date unless geometry differs.
- Store SeatLayer ids alongside your own immutable ids at creation time.
- Use deterministic idempotency keys for provisioning retries.
- Enforce ownership in your backend before every cross-tenant action.
- Keep master charts separate from organiser-owned copies.
- Test sandbox and live webhook routing through the same tenant checks.
- Expose only the operations your product is ready to support.
Custom-to-custom checklist
Before shipping a new product shape, write down:
- which system owns venues, events, prices, inventory, orders, and customers;
- how your ids map to
workspaceId, chart id, event key, hold id, andbookingRef; - which surface is embedded and which is called server-to-server;
- how a hold expiry, booking conflict, and payment failure recover;
- how tenant isolation is enforced and tested; and
- which webhooks reconcile your downstream systems.
Then use integration best practices and the complete checkout example to implement the buyer-to-booking loop.