---
title: "Embed sessions"
description: "Mint short-lived, origin-bound browser credentials for the embedded Designer and event control room."
---

Never expose an `sk_…` secret key to a browser. After your backend authorizes the
signed-in user, ask SeatLayer to mint a short-lived embed session for exactly the
chart editor or event operator surface that user may open.

| Token | Surface | Resource scope | Authorization scope |
|---|---|---|---|
| `dse_…` | Embedded Designer | One workspace and chart | `read-only`, `edit`, or `publish` |
| `mse_…` | SeatManager control room | One event | Explicit event capabilities |

Both tokens are bound to an exact browser origin, returned only when created,
stored by SeatLayer as hashes, expire automatically, and can be revoked.

<FlowDiagram
  label="Browser embed-session trust boundary"
  steps={[
    {
      actor: "Browser",
      title: "Requests an allowed surface",
      detail: "Your application identifies the signed-in user and the chart or Event they may open.",
      tone: "buyer",
    },
    {
      actor: "Your backend",
      title: "Authorizes the request",
      detail: "It decides the resource, allowed origin, authority, and expiry before making a SeatLayer call.",
      tone: "platform",
    },
    {
      actor: "SeatLayer",
      title: "Mints one scoped session",
      detail: "Your server uses its secret key to receive a short-lived dse_ or mse_ token after authorization succeeds.",
      tone: "seatlayer",
    },
    {
      actor: "Your backend",
      title: "Returns only the session",
      detail: "The browser receives the scoped token and expiry, never the account secret key.",
      tone: "platform",
    },
    {
      actor: "Browser",
      title: "Uses scoped operations",
      detail: "The embedded surface works only from the exact allowed origin and within its issued authority.",
      tone: "buyer",
    },
  ]}
/>

## Shared rules

- `expiresInSeconds`: 300–14,400; default 3,600.
- `allowedOrigin`: exact HTTPS origin, with no path, query, fragment, username,
  or password.
- Development allows `http://localhost` and `http://127.0.0.1`.
- Mint responses carry `Cache-Control: no-store`.
- Never log a raw token or token-bearing Designer URL.
- Revoking a session invalidates the credential without deleting the chart or
  changing event inventory.

Buyer `bse_…` credentials use a separate contract and expiry range. Ordinary
Platform Public sale uses direct `publicKey` bootstrap; scoped private audiences
use the [buyer access session endpoint](/server-api/buyer-access-sessions/).

## Designer session

<ApiEndpoint method="POST" path="/v1/designer/sessions" auth="Secret key" />

```bash
curl -sX POST "https://api.seatlayer.io/v1/designer/sessions" \
  -H "authorization: Bearer $SEATLAYER_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{
    "workspaceId": "ws_organizer_42",
    "chartId": "chart_main_hall",
    "allowedOrigin": "https://admin.example.com",
    "authority": "edit",
    "mode": "safe",
    "safeModeOptions": {
      "allowDeletingObjects": false,
      "allowEditingAreaCapacity": false
    },
    "expiresInSeconds": 3600
  }'
```

### Designer authority

| Authority | Read | Save draft | Publish |
|---|---:|---:|---:|
| `read-only` | Yes | No | No |
| `edit` | Yes | Yes | No |
| `publish` | Yes | Yes | Yes |

Prefer `authority`. Legacy `canPublish` remains compatible, but do not send
conflicting values. When neither is supplied, the session has `edit` authority.

`mode: "safe"` restricts destructive editing for a delegated organizer. Its
options can independently allow object deletion or area-capacity edits.
Feature policy can further limit the public Designer feature set; treat the
session response as the effective policy.

The response includes:

```json
{
  "session": {
    "id": "dsess_1f0e",
    "token": "dse_9c1b",
    "workspaceId": "ws_organizer_42",
    "chartId": "chart_main_hall",
    "allowedOrigin": "https://admin.example.com",
    "authority": "edit",
    "canEdit": true,
    "canPublish": false,
    "mode": "safe",
    "expiresAt": 1767207600000,
    "designerUrl": "https://app.seatlayer.io/embed/designer#token=dse_9c1b"
  }
}
```

The token is in the URL fragment, so it is not sent as part of the iframe's
initial HTTP request.

### Start before the click

The server trust boundary is required; a browser must never receive `sk_…` or
mint its own `dse_…`. The extra wait on the final click is not required. Once the
host has authenticated the user and resolved their chart and role, it can start
the no-store session request on route intent or page load while the SDK and
editor shell load. A server-rendered authenticated page may instead include the
short-lived `designerUrl` in a no-store bootstrap. Keep it in memory, mount it as
soon as the SDK is ready, and revoke it when access ends.

<ApiEndpoint method="DELETE" path="/v1/designer/sessions/:id" auth="Secret key" />

## Manage session

<ApiEndpoint method="POST" path="/v1/events/:key/manage-sessions" auth="Secret key or authorized dashboard session" />

```bash
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"],
    "expiresInSeconds": 3600
  }'
```

| Capability | Allows |
|---|---|
| `event:view` | Live board, section rules, and checkout-window reads |
| `event:block` | Block/unblock, section availability, and hold-TTL writes |
| `event:categories:manage` | Event-only object category assignments; reusable chart and existing price snapshots stay unchanged |
| `event:tables:manage` | Event-only table booking-mode changes for free inventory |
| `event:cancel` | Booking-reference-guarded cancellation |
| `event:reports` | Inventory report, CSV, audit log, and configured booked-value projection |
| `event:channels:view` | Channel inventory, allocation, audit, preview, and channel-report reads |
| `event:channels:manage` | Channel lifecycle, assignments, and hosted access-link management |
| `event:orders:read` | Managed Ticketing Order, CSV, detail, and timeline reads |
| `event:refund` | Managed Ticketing gateway refund |
| `event:tickets:send` | Managed Ticketing ticket resend |
| `event:door:view` | Door preflight, attendance, and attendance CSV |
| `event:door:checkin` | Door check-in mutation |
| `event:boxoffice` | Managed Ticketing counter inventory and sale |

Omitting `capabilities` is accepted for compatibility and grants only
`event:view`. It never grants a mutation, cancellation, report, channel, or
Managed Ticketing capability. Send the smallest explicit non-empty list whenever
the operator needs more than the live read-only board. Empty, null, malformed,
or unknown capability values are rejected.

Managed Ticketing capabilities are available only on a Managed Ticketing event.
Channel and commerce grants remain independent: for example, `event:boxoffice`
does not allow a token to cross a private allocation without the separately
granted `event:channels:manage` capability.

<ApiEndpoint method="DELETE" path="/v1/events/:key/manage-sessions/:id" auth="Secret key" />

The event key in the revoke path is part of the authorization scope. A session
can be revoked only under its exact event. Another event or organization returns
`404`; a same-organization key in the wrong live/test mode returns
`403 mode_mismatch`.

## Rotate long-running sessions

For `SeatManager`, pass `tokenExpiresAt` and `onTokenRefresh`. Ask SeatLayer for
the replacement from your backend with the same event, origin, and capabilities,
then return `{token, expiresAt}`. The SDK swaps it without rebuilding the board.

For `EmbeddedDesigner`, implement `onRequestRelaunch`, ask SeatLayer for a fresh
Designer session from your backend, and call `setDesignerUrl()`. Automatic
renewal uses the expiry reported by the embedded app.

## Backend session-endpoint pattern

Your own session route must check before it asks SeatLayer to mint:

1. the user is authenticated;
2. the user belongs to the host tenant;
3. the stored SeatLayer workspace/event belongs to that tenant;
4. requested authority or capabilities match the user's role;
5. the requested origin is on your allowlist.

Return only the scoped session response. Keep `SEATLAYER_SECRET_KEY` in the
server runtime.

Continue to [embedded Designer](/platform/embedded-designer) or
[embedded control room](/platform/embedded-control-room).