SeatManager is a same-document operator board—not an iframe. It renders the
event map, subscribes to live inventory, shows occupancy and activity, and
exposes controlled custom selection, blocking, category, table, section,
channel, cancellation, and reporting tools.
Trust boundary
Your backend authorizes the operator and asks SeatLayer to mint an event-scoped
mse_… token.
The browser receives only that token. Never put an account secret key in the
page.
Operator browserRequests Event access
The operator opens your application and asks for the control room for one Event.
Your backendGrants explicit capabilities
It authorizes the operator, then mints an mse_ token for the Event, origin, and exact allowed actions.
BrowserMounts SeatManager
The page receives only the temporary token and expiry, not an account secret key.
SeatLayerProvides live scoped operations
SeatManager reads live inventory and can perform only the actions the issued capability permits.
Mint a manage session
curl -sX POST \
"https://api.seatlayer.io/v1/events/ev_9f3a/manage-sessions" \
-H "authorization: Bearer $SEATLAYER_SECRET_KEY" \
-H "content-type: application/json" \
-d '{
"allowedOrigin": "https://admin.example.com",
"capabilities": [
"event:view",
"event:block",
"event:categories:manage",
"event:tables:manage",
"event:reports"
],
"expiresInSeconds": 3600
}'Add event:cancel only for operators allowed to return booked inventory to
sale. A browser manage token cannot confirm a booking: the platform backend
does that through /book. Managed Box Office is a separate commerce surface
and capability.
If your backend omits capabilities, the API issues a view-only token with
exactly event:view. Blocking, cancellation, reports, channels, and Managed
Ticketing operations always require an explicit capability.
Mount the board
import { SeatManager } from "@seatlayer/js/manager";
const session = await fetch("/api/events/ev_9f3a/manage-session", {
method: "POST",
}).then((response) => response.json());
const room = new SeatManager({
container: "#control-room",
eventKey: "ev_9f3a",
token: session.token,
tokenExpiresAt: session.expiresAt,
mode: "view",
keepLiveWhileHidden: true,
followLive: false,
onTokenRefresh: async () => {
const next = await fetch("/api/events/ev_9f3a/manage-session", {
method: "POST",
}).then((response) => response.json());
return { token: next.token, expiresAt: next.expiresAt };
},
onError: (error) => showOperatorError(error),
});
await room.render();Give the container a real height. SeatManager fills that box and watches it with
ResizeObserver. Fullscreen uses the browser Fullscreen API.
Operator modes
Tools are grouped in the toolbar as Watch (view, inspect — read-only),
Manage (block, sections, categories, tables, channels — changes
this event only) and Host tools (select, filterSections — hands a
selection or filter to your app). Pass tools to offer a subset; it filters
what is shown and never grants a capability.
| Mode | Purpose | Capability |
|---|---|---|
view |
Live occupancy, activity, momentum, presence, and aggregate inventory performance | event:view |
inspect |
Read the current state and context of one seat | event:view |
select |
Select live event objects for a host-owned custom operation; no inventory mutation | event:view |
filterSections |
Filter and frame matching section labels for host-owned reporting | event:view |
block |
Select and block/unblock individual inventory | event:block |
sections |
Open, close, hide, or schedule sections/zones | event:block |
categories |
Change event-only category assignments | event:categories:manage |
tables |
Change free tables between per-chair and whole-table booking | event:tables:manage |
channels |
Inspect or manage private sales allocations | event:channels:view / event:channels:manage |
event:reports is separate from the live board. Add it only when the embedded
staff workflow must open booking history, category/section/channel breakdowns,
downloadable inventory reports, or the full audit history. SeatLayer Orders,
tickets, refunds, and attendance are not part of the Platform/SDK Control room.
Following live activity is off by default so a busy event does not repeatedly move the operator’s camera. Heat overlays express sales velocity without replacing chart category colors.
Common actions
room.setMode("block");
room.selectSection("sec-stalls");
await room.block(undefined, {
releaseAt: Date.parse("2026-08-01T19:00:00Z"),
reason: "Soundcheck hold",
});
await room.unblock(["A-3"]);
await room.unblockAll();
await room.cancelBooking(["C-14", "C-15"], "order_5567");
await room.setHoldTtl(10 * 60 * 1000);
room.setMode("select");
room.selectObjects(["A-1", "A-2"]);
const selectionState = room.getSelectionValidity();
room.setMode("filterSections");
const matchedSections = room.setFilteredSection("Balcony");
room.clearFilteredSection();
await room.setCategory("vip", ["A-1", "A-2"]);
await room.setTableBooking(["table-1"], "whole");
const report = await room.getReport();
const log = await room.getLog({ limit: 50 });Cancellation changes inventory only; your application owns its commercial order, ticket cancellation, refund policy, payment execution, and buyer communication. The booking reference prevents releasing a newer booking.
Category assignments are event-only: the reusable venue chart is unchanged, and existing hold/booking price snapshots are not rewritten. Table-mode changes alter inventory identity and are therefore refused while any affected table is held, booked, or blocked, or when a private-channel allocation would be lost.
Long-running boards
Pass both tokenExpiresAt and onTokenRefresh. SeatManager proactively
requests a replacement and also retries once after an authorization failure.
Your refresh endpoint must repeat the full host-user authorization check rather
than accepting the expired token as proof.
keepLiveWhileHidden: true forces a fresh paint after live deltas when browsers
throttle background animation frames. Use it for a wallboard; consider battery
and resource costs on laptops.
Custom operator UI
Use ManageApi when the packaged board does not match your workflow. It exposes
the same token-authenticated reads and mutations: availability, category/table
management, block/unblock, cancellation, hold TTL, report, control-room
snapshot, audit log, and CSV Blob.
Keep capability rules identical to SeatManager.
Verification
- The backend authorizes event and tenant before every SeatLayer session request.
- The token carries only necessary capabilities.
- The board has a bounded, responsive container.
- Token rotation is tested across laptop sleep and network loss.
- Detailed reports and full audit history stay unavailable unless
event:reportsis minted. - Cancellation is paired with an explicit refund workflow.
- Conflict errors ask the operator to reload or reselect.
-
destroy()runs during unmount and logout. - Revocation occurs when access ends.
Continue to the SeatManager reference, embed sessions, and reports.