A workspace is SeatLayer’s resource-isolation boundary. Every chart and event belongs to exactly one workspace; billing, API keys, webhooks, and team roles belong to the organization.
Organization
├─ account, team, API keys, plan, credits, currency, webhooks
├─ Workspace A
│ └─ charts, events, embed sessions
└─ Workspace B
└─ charts, events, embed sessionsUse one workspace per organizer or customer for a multi-tenant platform. Smaller teams can use workspaces for venues, brands, regions, or environments.
Isolation contract
workspaceIdis enforced by SeatLayer, not just a routing tag.- A chart’s workspace is immutable.
- An event inherits the published chart’s workspace.
- Cross-workspace chart/event and chart/session pairings return
404. - List endpoints resolve one active workspace at a time.
- A disabled workspace is unavailable to normal resource reads and creates.
- Billing and team roles are still organization-wide.
List workspaces
/v1/workspacesSecret key or dashboard sessioncurl -s "https://api.seatlayer.io/v1/workspaces" \
-H "authorization: Bearer $SEATLAYER_SECRET_KEY"Create a workspace
/v1/workspacesSecret key or admin dashboard sessioncurl -sX POST "https://api.seatlayer.io/v1/workspaces" \
-H "authorization: Bearer $SEATLAYER_SECRET_KEY" \
-H "idempotency-key: workspace_customer_123" \
-H "content-type: application/json" \
-d '{
"name": "Customer 123",
"externalRef": "customer_123"
}'name is required and at most 120 characters. externalRef is optional, at
most 128 characters, and unique within the organization.
{
"workspace": {
"id": "ws_8b5c",
"name": "Customer 123",
"externalRef": "customer_123",
"status": "active",
"isDefault": false,
"createdAt": 1761436800000,
"updatedAt": 1761436800000
}
}Always use Idempotency-Key during tenant provisioning and store the returned
workspace id on your tenant record.
Read one workspace
/v1/workspaces/:idSecret key or dashboard sessionAn id from another organization returns 404, avoiding cross-tenant resource
disclosure.
Update, disable, or make default
/v1/workspaces/:idAdmin dashboard session only{
"name": "Customer 123 — Europe",
"externalRef": "customer_123",
"status": "active",
"isDefault": true
}This route deliberately rejects secret keys with
workspace_admin_session_required. externalRef: null clears the tag.
isDefault can only be set to true. The default workspace cannot be disabled;
promote another active workspace first.
Scope charts and events
curl -s \
"https://api.seatlayer.io/v1/events?workspaceId=ws_8b5c&externalRef=show_42" \
-H "authorization: Bearer $SEATLAYER_SECRET_KEY"When a secret-key request omits workspaceId, SeatLayer resolves the
organization’s default workspace. Platform code should pass it explicitly to
avoid accidental placement.
Canonical tenant provisioning
- Authorize the platform administrator in your application.
- Create a workspace with a stable idempotency key.
- Persist
workspace.idbeside your tenant id. - Duplicate or create charts in that workspace.
- Create events from charts in the same workspace.
- Mint browser embed sessions scoped to that workspace or its event.
- Route webhooks using the explicit
workspaceIdand your own stored mapping. - Aggregate tenant usage from its events; the credit wallet remains org-wide.
Checklist
- Every host tenant record stores an immutable workspace id.
- Every list and create request passes the intended workspace explicitly.
-
externalRefis used for reconciliation only. - Your application enforces per-tenant roles above SeatLayer’s org-wide roles.
- Disabled-workspace behavior is handled as an operator state, not a 500.
- Provisioning retries reuse one idempotency key and body.
Continue to platform integration, embedded Designer, and embed sessions.