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";
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 |
type SeatManagerMode = "view" | "inspect" | "block" | "sections";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 |
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 |
selectAll() |
Select all blockable seats |
selectSection(sectionId) |
Select section |
selectByLabels(labels) |
Select exact labels |
clearSelection() / getSelection() |
Manage block selection |
getReport() |
Private event report |
getControlRoomSnapshot(minutes?) |
Revenue, 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 |
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.
Gross revenue comes from authenticated booked-price snapshots and is never
reconstructed from the current list price.
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 booked-revenue values.
Action results
interface SeatManagerActionResult {
action:
| "block"
| "unblock"
| "unblockAll"
| "cancelBooking"
| "setHoldTtl";
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";
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, 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.