SeatBuilderSeatBuilder Docs

SDK reference

Hand-authored reference for the SeatBuilder browser SDK — install options, the full SdkConfig field table, callbacks, the ChartInstance surface, the React component, and a worked render() example.

SDK reference

The SeatBuilder browser SDK renders an interactive seat map inside your page and manages seat selection and holds against the SeatBuilder API. You embed it by calling SeatBuilder.render(config), which returns a ChartInstance you can drive imperatively. The SDK authenticates with your public key (pk_live_… / pk_test_…) — the browser render credential — so it is safe to ship in client code.

This page is the canonical, hand-authored reference. The full auto-generated type reference is linked at the bottom.

Install

The SDK is published to npm as @seatbuilder/sdk (ESM, TypeScript types included; konva and zod install automatically):

npm install @seatbuilder/sdk
import SeatBuilder from '@seatbuilder/sdk';
import type { SdkConfig, ChartInstance } from '@seatbuilder/sdk';

Or load the script-tag bundle, which exposes a window.SeatBuilder global:

<script src="https://seatbuilder.org/sdk/latest/seatbuilder.iife.min.js"></script>

React apps can use the <SeatBuilderChart> component from @seatbuilder/sdk/react instead of calling render() directly.

SDK 5.7.x requires SeatBuilder server v1.16.0+. 5.7 moved own-hold detection to the server (/status ?holdToken= → mine / mineQuantity) and scopes release to a holdToken. An older SDK against a v1.16.0+ server keeps rendering, but its own holds show as held-by-other after a refresh and deselect-release fails (the seat still frees itself at hold expiry) — upgrade to 5.7.1 for hold-mode embeds. See the changelog for the full release notes.

Configuration (SdkConfig)

Pass a single config object to SeatBuilder.render(). Every field below is transcribed from packages/sdk/src/types.ts.

FieldTypeRequiredDefaultDescription
publicKeystringYes—Public API key (pk_live_… / pk_test_…). This is the browser render credential.
eventKeystringYes—Event key (UUID or slug).
containerHTMLElement | stringYes—DOM element or element ID string to mount into.
apiUrlstringYes—Base URL of the SeatBuilder API (e.g. https://seatbuilder.org). Required since 1.0.0 — the SDK throws at construction if it is absent.
maxSelectedObjectsnumber | { total?: number; perCategory?: Record<string, number> }NounlimitedSeat selection cap. A bare number is the total cap; the object form adds per-category caps (both enforced when set together).
showSeatLabelsbooleanNofalseShow seat-number labels on the map (hidden below ~0.43× zoom regardless).
holdDurationSecondsnumberNoserver default 900 (no client default)Passed as ttlSeconds on the initial /hold. Omit to use the server default of 900s — there is no silent client default; the field is simply absent from the /hold body when unset. 300 is only an example value, not a default.
showHoldCountdownbooleanNofalseRe-enable the built-in 2-minute warning banner + auto-deselect timer.
selectionMode'hold' | 'select'No'hold''hold' = buyer purchase flow; 'select' = operator selection-only (no /hold round-trip). Advanced/operator use.
languagestringNo'en'BCP-47 language code selecting a built-in string catalog for every user-facing SDK string (legend, tooltips, GA "N left"/"Sold out", hold/expiry/connection banners, quantity picker). Shipped catalogs: en (default) and vi (Vietnamese). An unset or unrecognized code falls back to en. Region subtags are ignored (vi-VN → vi).
messagesPartial<SdkMessages>No{}Per-string overrides merged over the selected catalog. Each provided key wins over both the language catalog and the en fallback. Plural keys (e.g. gaRemaining) take a { one, other } object; the override replaces the whole value.

Localization (language and messages)

Every built-in string the SDK renders — status-legend labels, seat/GA tooltips, the GA "N left" / "Sold out" text, the hold-warning, hold-expired, and connection-lost banners, and the GA quantity picker — is drawn from a typed string catalog. Set language to pick a shipped catalog, and/or pass messages to override individual keys:

SeatBuilder.render({
  container: '#chart',
  apiUrl: 'https://seatbuilder.org',
  publicKey: 'pk_live_…',
  eventKey: 'my-event',
  language: 'vi',
  messages: { sold: 'Đã bán' },
});

Resolution is per-key: an override wins over the language catalog, which wins over the en fallback. A missing or blank value can never reach the DOM — an unresolved key always falls back to en. The SdkMessages type is re-exported from @seatbuilder/sdk if you want to author a complete standalone catalog.

A note on holdDurationSeconds and the hold TTL

holdDurationSeconds is the single client-side control over the browse-hold lifetime. When set, it is sent as ttlSeconds on the initial POST /hold. When you omit it, the field is absent from the request body and the server default of 900 seconds applies. There is no separate silent client default, and 300 (seen in some examples) is only an illustrative shorter value, not a built-in default.

Select mode (selectionMode: 'select')

selectionMode defaults to 'hold' — the buyer purchase flow, where clicking a free seat calls POST /seats/hold immediately. Set selectionMode: 'select' for an operator/admin selection tool instead: clicking any seat (free, held, or booked) just toggles its local selection state for your own UI to read back — the SDK never calls /hold or /release in this mode. There is no round-trip, no holdToken reservation, and nothing is written to the server from selection alone; your own backend decides what to do with the selected labels (e.g. force-release via the server-side /release API with a secret key).

Seats held or booked by other sessions are still shown as unavailable (the held-by-other / booked visual states) — in select mode this comes entirely from the live snapshot and realtime feed described below, never from a hold the SDK itself took. Live cross-user updates reach the chart the same way in both modes: a WebSocket subscription pushes seat.held / seat.booked / seat.released / seat.hold_expired deltas as they happen, and on connect or reconnect the SDK does a full GET /status refetch to reconcile before applying any further deltas — so a select-mode operator view stays live without ever holding a seat itself.

Callbacks

All callbacks are optional and passed alongside the config fields above (SdkConfig extends SdkCallbacks).

CallbackPayload fields
onObjectSelected(event)objectLabel, holdToken, categoryKey
onObjectDeselected(event)objectLabel
onSelectionValid(event)selectedObjectLabels[]
onSelectionInvalid(event)selectedObjectLabels[], reason ('max_selected' | 'hold_expired' | 'hold_failed'), categoryKey?
onChartRendered(event)chartData

Chart instance (ChartInstance)

SeatBuilder.render() returns a ChartInstance for imperative control:

MemberSignaturePurpose
holdTokenstring (readonly)Current session hold token — share with your backend to extend, book, or release the held seats.
clearSelection(): voidDeselect all seats and release holds.
selectObjects(labels: string[]): Promise<void>Programmatically select seats by objectLabel.
refreshStatus(): Promise<void>Re-fetch the server status snapshot and repaint every seat in place (operator dashboard use).
destroy(): voidDestroy the chart and clean up all resources.

The holdToken is the link between the browser session and your server: pass it to the backend extend / book / release endpoints to confirm or free the buyer's seats.

Worked example

Render a chart with the public key and read back the session hold token:

import SeatBuilder from '@seatbuilder/sdk';

const chart = SeatBuilder.render({
  publicKey: 'pk_live_xxx',
  eventKey: 'evt_summer_gala',
  container: '#seatmap',
  apiUrl: 'https://seatbuilder.org',
  onObjectSelected: ({ objectLabel, categoryKey }) => {
    console.log(`selected ${objectLabel} (${categoryKey})`);
  },
});

// Hand this token to your backend to book or release the held seats.
async function checkout() {
  await fetch('/api/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ holdToken: chart.holdToken }),
  });
}

A minimal render with a selection cap and shorter browse hold:

import SeatBuilder from '@seatbuilder/sdk';

const chart = SeatBuilder.render({
  publicKey: 'pk_live_xxx',
  eventKey: 'evt_summer_gala',
  container: '#seatmap',
  apiUrl: 'https://seatbuilder.org',
  maxSelectedObjects: { total: 6, perCategory: { vip: 2 } },
  holdDurationSeconds: 300,
});

React component (SeatBuilderChart)

@seatbuilder/sdk/react exports SeatBuilderChart, a client component that calls SeatBuilder.render() for you (React 18+). It is safe to render from a Next.js App Router server component tree — the chart mounts on the client.

'use client';
import { useRef } from 'react';
import { SeatBuilderChart } from '@seatbuilder/sdk/react';
import type { ChartInstance } from '@seatbuilder/sdk';

export function SeatMap({ eventKey }: { eventKey: string }) {
  const chart = useRef<ChartInstance | null>(null);
  return (
    <SeatBuilderChart
      ref={chart}
      publicKey="pk_live_xxx"
      eventKey={eventKey}
      apiUrl="https://seatbuilder.org"
      onObjectSelected={({ objectLabel }) => console.log('held', objectLabel)}
      style={{ height: 600 }}
    />
  );
}
PropTypeDescription
every SdkConfig field except containersee ConfigurationPassed through to render(); the component creates its own container <div>.
onReady(chart: ChartInstance | null) => voidCalled with the live instance after render, and with null on teardown.
className / stylestring / CSSPropertiesApplied to the container <div> — give it a height.
refRef<ChartInstance | null>The live ChartInstance; null until the chart mounts.

Re-mount rules: changing an on* callback, onReady, className or style never re-mounts the chart; changing any config field (e.g. eventKey, maxSelectedObjects) destroys it and renders a new one. Unmounting destroys the chart — don't call destroy() yourself. See the React & Next.js recipe for a full walkthrough.

Full generated reference

Every exported symbol is also documented in the auto-generated TypeDoc tree:

SDK reference — SeatBuilder Docs