SeatBuilderSeatBuilder Docs

Authentication

How API keys authenticate every SeatBuilder REST call — public vs secret keys, the X-Api-Key header, environments, and workspace scope.

Authentication

Every request to the public SeatBuilder REST API authenticates with a single header: X-Api-Key. Keys are workspace-scoped and bound to a single environment (production or sandbox). There is no OAuth, no session cookie, and no JWT for API consumers — those flows are reserved for the dashboard UI.

API key types

Each workspace uses two kinds of key per environment:

PrefixPurposeWhere it lives
pk_live_*Publishable — safe to embed in browser codeSDK publicKey option
sk_live_*Secret — server-side onlyBackend env var (SEATS_API_KEY)
pk_test_*Publishable, sandbox environmentSDK publicKey during testing
sk_test_*Secret, sandbox environmentBackend env var during testing

How keys are provisioned differs by type. Your publishable (pk_live_* and pk_test_*) keys are seeded automatically when the workspace is created and are usable immediately — the value you see on the dashboard API keys page is the full key, so you can copy it straight into your SDK publicKey option.

Secret (sk_live_* and sk_test_*) keys are not created automatically. Create each secret key on demand from the dashboard API keys page, where its plaintext value is shown exactly once at creation time. Copy it into your backend secret store right away — the value is never displayed again. If you lose a secret key, rotate it from the same page to mint a replacement (the old value stops working immediately). Create your secret key before you need it server-side.

Publishable (pk_*) keys are scoped to the buyer-facing seat-selection routes, and only part of that surface — some seat actions are secret-key only:

Endpointpk_* (public)sk_* (secret)
GET event, GET /status, GET /objectsYesYes
POST /seats/holdYesYes
POST /seats/bookNo — 403 public_key_not_allowedYes
POST /seats/extendNo — 403 public_key_not_allowedYes
POST /seats/releaseOnly with holdToken, and only frees rows status: 'held' under that exact token — booked seats are never released by a public keyYes — with a holdToken (held + booked) or without one (any held/booked seat, admin release)
POST /events/{eventKey}/resetNo — 403 public_key_not_allowedYes — sandbox events only (403 sandbox_only in production)
Chart creation, webhook management, and everything elseNoYes

Use publishable keys in browser code where the key value is visible to the buyer. book and extend are server-side actions by design — a buyer's browser can select and hold seats, but only your backend confirms the sale or extends the payment window. Never ship sk_* keys to a browser. See Error model for the exact code values above.

The X-Api-Key header

Pass your key in the X-Api-Key request header. The server hashes the key on receipt and looks it up in the workspace's key table.

curl -H "X-Api-Key: sk_live_xxx" \
  https://seatbuilder.org/api/v1/charts

Calls with a missing or malformed key return 401 Unauthorized. Calls with a syntactically valid key whose hash isn't on file return 401 Unauthorized as well — the server does not distinguish unknown keys from forged keys to keep enumeration noisy. See Error model for the full error envelope.

Environments

Each workspace has two isolated environments: production and sandbox. Keys cannot cross environments. A pk_test_* key cannot read production events, and a pk_live_* key cannot reach sandbox data.

Isolation applies to events, holds, and bookings — not to charts. Events, seat holds, and bookings are strictly environment-scoped: a *_test_* key can never read or write a production event's seats, and vice versa. Charts, however, are a workspace-level design asset: GET /charts lists every chart in the workspace regardless of which environment(s) its events use, and both a pk_live_* and a pk_test_* key can read the same chart's published layout. This is deliberate — a chart is a seat-map template you design once and reuse across production and sandbox events, not per-environment data.

In practice this means:

  • Develop and test against *_test_* keys hitting your sandbox environment. Seat state — holds, bookings, /status — never leaks between environments.
  • Promote to *_live_* only when your integration is verified — the sandbox is rate-limited and may be reset (see POST /events/{eventKey}/reset in Hold and book lifecycle).
  • Don't rely on a chart key being environment-scoped — it isn't. Scope your own access control around events, not charts, if that distinction matters to your integration.

Workspace scope

Keys are bound to one workspace. Every authenticated request auto-scopes to that workspace's data — charts, events, webhooks, and seat state are all isolated from other workspaces. There is no API surface for reading data across workspaces; misconfigured cross-workspace requests return 403 Forbidden.

This is the only safe assumption a multi-tenant integration can make: if a buyer presents a hold token from another workspace's event, the book request rejects with 403 before any state mutation runs.

Authentication — SeatBuilder Docs