Skip to content

SeatManager reference

SeatManager options, modes, callbacks, methods, data authority, and the lower-level ManageApi.

Updated View as Markdown

SeatManager is the complete operator SDK surface. It mounts a native canvas and control rails in your document, subscribes to live state, and sends private actions with an event-scoped manage token.

import { SeatManager } from "@seatlayer/js/manager";

const room = new SeatManager({
  container: "#control-room",
  eventKey: "ev_9f3a",
  token,
});

await room.render();

Constructor options

Option Type Required Notes
container string | HTMLElement Yes Must resolve to a sized element
eventKey string Yes One event
token string Yes Browser-safe mse_…; never expose sk_…
apiBase string No Defaults to https://api.seatlayer.io
tokenExpiresAt number No Epoch ms; enables proactive rotation
mode SeatManagerMode No Default view
currency string No Fallback; event/chart currency wins
theme ChartTheme No Operator chrome override; canvas uses chart
keepLiveWhileHidden boolean No Default true
followLive boolean No Default false
selectedObjects string[] No Public labels preselected after live inventory loads in select mode
selectableObjects string[] No Labels allowed as exceptions when unavailable objects are otherwise excluded
unavailableObjectsSelectable boolean No Include held, booked, and blocked objects in select; default true
maxSelectedObjects number No Maximum custom-operation selection
numberOfPlacesToSelect number No Require exactly this many objects and use it as the selection cap
isObjectSelectable (object, defaultValue) => boolean No Final host policy for each object in select mode
capabilities SeatManagerCapability[] No Declared token capabilities used to hide/fail-close privileged tools
tools SeatManagerMode[] No Which tools the toolbar offers. Default: every tool the capabilities permit. Listing a tool never grants it, and view is always kept
type SeatManagerMode =
  | "view"
  | "inspect"
  | "select"
  | "filterSections"
  | "block"
  | "sections"
  | "categories"
  | "tables"
  | "channels";

view is the read-only live/static event view. select is a read-only custom-operation tool, while filterSections frames one public section label for host-owned reporting. None of those tools mutates inventory. categories and tables make event-only changes and are hidden unless their dedicated capabilities are declared.

The toolbar presents these in three labelled groups, so an operator can tell at a glance what a tab will do:

Group Tools What it means
Watch view, inspect Read-only. Nothing changes.
Manage block, sections, categories, tables, channels Changes this event only. The reusable chart is never edited.
Host tools select, filterSections Hands a selection or a filter to your app; the control room itself changes nothing.

Each rail repeats that scope as a badge next to its title (Read-only, This event only, Your app).

Use tools to hide what a surface does not need — a dashboard that never consumes onSelectionChange should not show a Select tab that leads nowhere:

new SeatManager({
  container: "#room",
  eventKey: "ev_123",
  token: manageToken,
  capabilities: ["event:view", "event:block", "event:categories:manage"],
  // Watch + Manage only. The whole "Host tools" group disappears.
  tools: ["view", "inspect", "block", "sections", "categories"],
});

tools is a filter, never a grant: a mode whose capability is missing stays hidden however it is listed, and any refused mode falls back to view.

Callbacks

Callback Signature
onReady () => void
onTallies (tallies: SeatManagerTallies) => void
onActivity (activity: SeatManagerActivity) => void
onControlRoom (snapshot: ControlRoomSnapshot) => void
onTokenRefresh () => Promise<{token: string; expiresAt: number}>
onModeChange (mode: SeatManagerMode) => void
onFollowLiveChange (enabled: boolean) => void
onSelectionChange (seats: ExpandedSeat[]) => void
onObjectSelected / onObjectDeselected (object: ExpandedSeat) => void
onSelectionValidityChange (state: SeatManagerSelectionValidity) => void
onSelectionValid / onSelectionInvalid (state: SeatManagerSelectionValidity) => void
onSelectionLimit (max: number) => void
onFilteredSectionChange (sections: SeatManagerFilteredSection[]) => void
onActionComplete (result: SeatManagerActionResult) => void
onError (error: unknown) => void

Methods

Method Result
render() Load, subscribe, and return Promise<this>
setMode(mode) Switch operator tool
setHeatOverlay(enabled) Toggle velocity outline
setFollowLive(enabled) Toggle camera following
setTrendWindow(minutes) Refresh and return control-room snapshot
enterFullscreen() / exitFullscreen() Native fullscreen
isFullscreen() Current fullscreen state
setToken(token, expiresAt?) Rotate credential without remount
block(labels?, {releaseAt?, reason?}) Block labels or current selection
unblock(labels?) Unblock labels or selection
unblockAll() Unblock all event inventory
cancelBooking(labels, bookingRef) Booking-reference-safe cancellation
setCategory(categoryKey, labels?) Assign an event-only category to labels or the selection
setTableBooking(tableIds, mode, bounds?) Change free event tables between per-chair, whole-table, or variable occupancy
selectAll() Select all blockable seats
selectSection(sectionId) Select section
selectByLabels(labels) Select exact labels
selectObjects(labels) / deselectObjects(labels) Custom selection by public label
selectCategories(keys) / deselectCategories(keys) Custom selection by chart category
setSelectableObjects(labels) Replace unavailable-object exceptions
setUnavailableObjectsSelectable(enabled) Include or exclude unavailable inventory
setObjectSelectable(predicate) Replace the final host selection policy
setMaxSelectedObjects(max?) Change or clear the custom selection cap
setNumberOfPlacesToSelect(required?) Change or clear exact-count selection
getSelectionValidity() Exact-count state, or null when no count is required
setFilteredSection(label) Filter and frame every section with this public label
clearFilteredSection() Clear filtering and restore the full event frame
getFilteredSections() Read all currently matched sections
clearSelection() / getSelection() Manage block selection
getReport() Private event report
getControlRoomSnapshot(minutes?) Booked value, velocity, presence, activity
getLog({limit?, before?}) Paginated audit log
setHoldTtl(msOrNull) Set or clear event checkout window
zoomToFit() Fit chart
destroy() Close socket, timers, and mounted UI

Event-only category and table controls

setCategory() changes the event snapshot and current free inventory pricing; it does not edit the reusable chart. Existing hold and booking line-item price snapshots remain immutable.

setTableBooking() changes inventory identity, so SeatManager reloads the authoritative event chart after success. The server refuses the operation when any affected table unit is held, booked, or blocked, or when changing labels would drop a private-channel assignment. Variable occupancy bounds must fit the physical table capacity. These controls require inventory model 2.

boxBook() exists as a compatibility stub in current package declarations. Do not call it. Use the server-side box-book route.

Tallies

interface SeatManagerTallies {
  free: number;
  held: number;
  booked: number;
  blocked: number;
  total: number;
  capacityPct: number;
  sellThroughPct: number;
  grossRevenue: number;
  revenueStatus: "loading" | "current" | "stale";
  currency: string;
}

capacityPct is booked divided by total capacity. sellThroughPct is booked divided by capacity excluding blocked inventory. grossRevenue and revenue are legacy SDK field names. They come from authenticated configured-price snapshots captured with booked inventory and should be labelled booked value in a Platform product. They are never reconstructed from the current list price, but they also do not prove the amount charged, settled, or refunded in your commerce system.

Control-room snapshot

interface ControlRoomSnapshot {
  version: number;
  currency: string;
  totals: {
    free: number;
    held: number;
    booked: number;
    blocked: number;
  };
  revenue: {
    gross: number;
    bySection: ControlRoomSectionMetric[];
  };
  velocity: {
    windowMinutes: number;
    bySection: Array<{
      sectionId: string;
      netBooked: number;
      grossRevenue: number;
      previousNetBooked: number;
      trend: "rising" | "steady" | "cooling";
    }>;
  };
  presence: {
    shoppingSessions: number;
    activeHolds: number;
  };
  activity?: ControlRoomActivityEntry[];
  event: {
    key: string;
    name: string;
    seatTotal: number;
    currency?: string;
  };
}

Section metrics include section and zone identity plus total, free, held, booked, not-for-sale, and configured booked-value snapshots.

Action results

interface SeatManagerActionResult {
  action:
    | "block"
    | "unblock"
    | "unblockAll"
    | "cancelBooking"
    | "setHoldTtl"
    | "setCategory"
    | "setTableBooking";
  labels: string[];
  count: number;
}

Errors from permission, conflict, expiry, and transport failures reach onError and reject the relevant promise. Do not infer success from an optimistic repaint.

ManageApi

ManageApi is the lower-level transport for custom operator interfaces:

import { ManageApi } from "@seatlayer/js/manager";

const api = new ManageApi("https://api.seatlayer.io", token);
const report = await api.report(eventKey);
const rules = await api.availability(eventKey);

It provides chart, objects, socketUrl, block, unblock, unblockAll, unbook, setCategory, setTableBooking, setHoldTtl, availability, setAvailability, report, controlRoom, log, and reportCsv. reportCsv() returns a Blob because a Bearer token cannot be attached to a plain download link.

Lifecycle

Call render() before imperative methods. Call destroy() on route changes, component unmount, logout, and event switching. Reuse setToken() for rotation rather than reconstructing the board.

See the control-room guide and manage-session security model.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close