---
title: "Workspaces"
description: "Isolate charts and events for organizers, customers, brands, venues, or environments inside one SeatLayer organization."
---

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.

```text title="workspace-model.txt"
Organization
  ├─ account, team, API keys, plan, credits, currency, webhooks
  ├─ Workspace A
  │    └─ charts, events, embed sessions
  └─ Workspace B
       └─ charts, events, embed sessions
```

Use one workspace per organizer or customer for a multi-tenant platform. Smaller
teams can use workspaces for venues, brands, regions, or environments.

## Isolation contract

- `workspaceId` is 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.

<Aside type="caution" title="externalRef is not authorization">
  `externalRef` helps you reconcile SeatLayer resources with your tenant ids.
  It does not isolate access. Authorize the user in your application, then use
  the stored `workspaceId`.
</Aside>

## List workspaces

<ApiEndpoint method="GET" path="/v1/workspaces" auth="Secret key or dashboard session" />

```bash
curl -s "https://api.seatlayer.io/v1/workspaces" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY"
```

## Create a workspace

<ApiEndpoint method="POST" path="/v1/workspaces" auth="Secret key or admin dashboard session" />

```bash
curl -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",
    "defaultRegion": "western-europe"
  }'
```

`name` is required and at most 120 characters. `externalRef` is optional, at
most 128 characters, and unique within the organization. `defaultRegion` is an
optional [Event region](/server-api/event-regions/); omitted workspace creates
use `western-europe`.

```json
{
  "workspace": {
    "id": "ws_8b5c",
    "name": "Customer 123",
    "externalRef": "customer_123",
    "status": "active",
    "isDefault": false,
    "defaultRegion": "western-europe",
    "createdAt": 1761436800000,
    "updatedAt": 1761436800000
  }
}
```

Always use `Idempotency-Key` during tenant provisioning and store the returned
workspace id on your tenant record.

## Read one workspace

<ApiEndpoint method="GET" path="/v1/workspaces/:id" auth="Secret key or dashboard session" />

An id from another organization returns `404`, avoiding cross-tenant resource
disclosure.

## Update, disable, or make default

<ApiEndpoint method="PATCH" path="/v1/workspaces/:id" auth="Secret key or admin dashboard session" />

```json
{
  "name": "Customer 123 — Europe",
  "externalRef": "customer_123",
  "status": "active",
  "isDefault": true,
  "defaultRegion": "western-europe"
}
```

Secret keys have account authority and may update an organization-owned
workspace through the Server API. Dashboard writes require an admin session.
`externalRef: null` clears the tag. `isDefault` can only be set to `true`. The
default workspace cannot be disabled; promote another active workspace first.
Changing `defaultRegion` affects only later Events. An Event may override it;
existing Events never move.

## Scope charts and events

```bash
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

1. Authorize the platform administrator in your application.
2. Create a workspace with a stable [idempotency key](/server-api/idempotency-and-conflicts/).
3. Persist `workspace.id` beside your tenant id.
4. Duplicate or create charts in that workspace.
5. Create events from charts in the same workspace.
6. Mint browser embed sessions scoped to that workspace or its event.
7. Route webhooks using the explicit `workspaceId` and your own stored mapping.
8. 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.
- [ ] `externalRef` is 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](/integrations/platforms),
[embedded Designer](/platform/embedded-designer), and
[embed sessions](/platform/embed-sessions).