Developers

Quickstart

SeatPublic keeps the seating chart, every seat's live status and the seat map. You keep checkout, payments, customers and tickets. The integration is three parts: your server creates the event and confirms each sale, and the buyer's browser shows the map and holds the seats they pick.

Everything below works with test keys against the sample theatre (demo-theatre). The API lives at https://api.seatpublic.com; every path starts with /v1, bodies are JSON, and errors look like { "error": "code" }.

Keys

Create an account in the dashboard and name your company: it gets test keys straight away. Send a key as the X-Api-Key header.

KeyWhere it goesWhat it can do
sk_test_… / sk_live_…Your server onlyCreate events, set prices, confirm sales, release seats
pk_test_… / pk_live_…Web pagesRead the event and map, receive live updates, hold seats

Test keys only see test events, and live keys only live ones. Live keys need a confirmed email. Never put a secret key in a web page, a log or a repository.

Step 1Create an event

Once per performance, from your server. venueId picks the venue's seating chart; the event keeps that chart version for as long as it's on sale.

POST /v1/events · secret key
curl -X POST https://api.seatpublic.com/v1/events \
  -H "X-Api-Key: $SEATPUBLIC_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{ "venueId": "demo-theatre", "startsAt": "2026-12-01T19:30:00Z" }'

→ 201 { "eventId": "ev_…", "chartId": "…", "chartVersion": 1, "environment": "test" }

Store eventId with your own event.

Step 2Set prices

Charts have price categories; your event decides what they cost. Overrides are optional and keyed by seat id or section id. Push your own prices here so the map shows exactly what checkout will charge.

PUT /v1/events/{eventId}/pricing · secret key
{ "categories": { "1": 120, "2": 78, "3": 45 },
  "overrides":  { "orchestra-A-5": 150 } }

Change them whenever you like: open maps update straight away. At checkout, ask the server for the real total with POST /v1/events/{eventId}/quote { "seatIds": [...] } instead of trusting prices sent from the browser.

Step 3Show the map

Load the script and add the tag with your publishable key. The map loads the chart, availability and prices, and stays live as other buyers hold and buy seats.

checkout.html
<script type="module" src="https://seatpublic.com/sdk/seatmap/v0/index.js"></script>

<seat-map api-base="https://api.seatpublic.com" event-id="ev_…"
          api-key="pk_test_…" max-selectable="8" no-orphan
          style="display:block; height:600px"></seat-map>

The element fires seatSelect, seatDeselect, holdCreated, holdExpired and error. It follows the reader's light or dark setting, and colours can be changed with --sc-* CSS properties.

Step 4Hold seats

When the buyer goes to pay, hold what they picked. A hold is all or nothing: either every seat is held or none are.

checkout.js
const map = document.querySelector("seat-map");
try {
  const hold = await map.live.holdSelection();   // { holdToken, expiresAt, seatIds }
  // send hold.holdToken to your server with the order
} catch (e) {
  // e.seats: the seats someone else just took. Nothing was held.
}

Step 5Confirm the sale

Only after the payment has succeeded, from your server:

POST /v1/events/{eventId}/confirm · secret key
{ "holdToken": "…", "orderRef": "your-order-id" }

→ 200 { "status": "sold", "seatIds": [...], "replayed": false }
→ 404 { "error": "hold_not_found_or_expired" }   not sold: refund or void the payment

Confirming is safe to repeat. After a timeout, call it again with the same hold and order: you get "replayed": true and the same seats, never a second sale.

Step 6Refunds

Refund in your system, then put the order's seats back on sale with POST /v1/events/{eventId}/seats/release { "orderRef": "your-order-id" }. GET /v1/events/{eventId}/orders/{orderRef} shows what an order holds right now.

Webhooks

Register an HTTPS endpoint with POST /v1/webhooks { "url": "…", "events": ["hold.expired", "hold.confirmed", "seats.released"] }. The response includes a secret, shown once.

Events: event.created, hold.created, hold.confirmed, hold.expired, seats.released, seat.status_changed, chart.version_published, event.cancelled, event.chart_changed, webhook.ping.

Box office screen

For staff, your server makes a short-lived pass for one event and one person with POST /v1/events/{eventId}/manager-tokens, and your page opens the seat manager with it. Staff can block seats, name holds, change categories and undo. Passes can never sell or refund: the screen hands those back to your own system.

Your own venues

Draw a venue in the chart editor, from a template, from scratch or traced over a floor plan. Sign in to the dashboard and the editor publishes for your organization; no key needed. Charts are shared: if someone has already published the venue, you'll be offered theirs, and improvements go in as reviewed edits.

Going live

API reference

CallKeyWhat it does
POST /v1/eventssecretCreate an event for a venue
GET /v1/events/{id}eitherThe event, its chart and version
GET|PUT /v1/events/{id}/pricingeither / secretPrices by category, overrides by seat or section
GET /v1/events/{id}/availabilityeitherEvery seat that isn't free; supports ETag
POST /v1/events/{id}/quoteeitherPrices and total for a list of seats
POST /v1/events/{id}/holdseitherHold 1–10 seats, all or nothing
PATCH|DELETE /v1/events/{id}/holds/{token}eitherExtend or release a hold
POST /v1/events/{id}/confirmsecretSell a hold to an order; safe to repeat
GET /v1/events/{id}/orders/{orderRef}secretThe seats an order holds now
POST /v1/events/{id}/seats/releasesecretPut an order's seats back on sale
PATCH /v1/events/{id}/seatssecretBlock, unblock or sell at the box office
POST /v1/events/{id}/cancelsecretCancel the event; lists the orders to refund
POST /v1/events/{id}/manager-tokenssecretA staff pass for the box office screen
POST /v1/webhookssecretRegister a webhook endpoint
GET /v1/charts/{id}/versions/{v}eitherA chart: sections and seats

Questions? Write to [email protected].