# Scenes API

Scenes of an overlay: create, prepare in preview and put them live.

Authenticate with a [personal token](/docs/api#personal-tokens) as `Authorization: Bearer pxp_...`; the operations are also [MCP tools](/docs/connect-ai) unless noted. The full machine-readable definition is in the [OpenAPI specification](https://pxstudio.cloud/api/v1/openapi.json).

| Operation | Method and path | Scope |
| --- | --- | --- |
| [List scenes](#list-scenes) | `GET /overlays/{overlayId}/scenes` | `overlays:read` |
| [Create scene](#create-scene) | `POST /overlays/{overlayId}/scenes` | `scenes:write` |
| [Rename scene or set its transition](#rename-scene-or-set-its-transition) | `PATCH /overlays/{overlayId}/scenes/{sceneId}` | `scenes:write` |
| [Delete scene](#delete-scene) | `DELETE /overlays/{overlayId}/scenes/{sceneId}` | `scenes:write` |
| [Duplicate scene](#duplicate-scene) | `POST /overlays/{overlayId}/scenes/{sceneId}/duplicate` | `scenes:write` |
| [Put scene on air](#put-scene-on-air) | `POST /overlays/{overlayId}/scenes/{sceneId}/golive` | `scenes:golive` |
| [Create preview of a scene](#create-preview-of-a-scene) | `POST /overlays/{overlayId}/scenes/{sceneId}/preview` | `scenes:write` |
| [Take preview to program](#take-preview-to-program) | `POST /overlays/{overlayId}/scenes/{sceneId}/take` | `scenes:golive` |
| [Set a layer's state in a scene](#set-a-layers-state-in-a-scene) | `PATCH /overlays/{overlayId}/scenes/{sceneId}/members/{memberId}` | `scenes:write` |
| [Reorder scenes](#reorder-scenes) | `PUT /overlays/{overlayId}/scenes/order` | `scenes:write` |

## Operations

### List scenes

```http Endpoint
GET /api/v1/overlays/{overlayId}/scenes
```

Lists the scenes of an overlay and which one is live (activeSceneId).

**Scope:** `overlays:read` (Read overlays) · **MCP tool:** `list_scenes` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes`, {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create scene

```http Endpoint
POST /api/v1/overlays/{overlayId}/scenes
```

Creates a scene. mode "blank" (default) starts with every layer hidden; "snapshot" copies the current live state. A new scene is never live until you call go_live_scene. Supports the Idempotency-Key header.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `create_scene` · **Notes:** supports Idempotency-Key

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `name` | body | string | required | Up to 40 characters |
| `mode` | body | `blank`, `snapshot` | optional |  |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "..." }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: "..." }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Rename scene or set its transition

```http Endpoint
PATCH /api/v1/overlays/{overlayId}/scenes/{sceneId}
```

Renames a scene and/or sets the transition used when it goes live (morph, fade, slide, zoom, cut; 200-2000 ms).

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `update_scene`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |
| `name` | body | string | optional | Up to 40 characters |
| `transitionType` | body | `morph`, `fade`, `slide`, `zoom`, `cut` | optional |  |
| `transitionMs` | body | integer | optional | 200 to 2000 |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "...", "transitionType": "morph" }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: "...", transitionType: "morph" }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Delete scene

```http Endpoint
DELETE /api/v1/overlays/{overlayId}/scenes/{sceneId}
```

DESTRUCTIVE: deletes a scene. The live scene and the last scene cannot be deleted.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `delete_scene` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |

::: tabs
@@ cURL
```bash
curl -X DELETE "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}`, {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Duplicate scene

```http Endpoint
POST /api/v1/overlays/{overlayId}/scenes/{sceneId}/duplicate
```

Copies a scene (every layer's position, stacking and visibility plus the transition) under "<name> copy". The copy is never live until you call go_live_scene; it counts against the scene limit.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `duplicate_scene`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>/duplicate" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}/duplicate`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Put scene on air

```http Endpoint
POST /api/v1/overlays/{overlayId}/scenes/{sceneId}/golive
```

ON AIR: switches the live stream output to this scene immediately (viewers see it). Prefer preview_scene + take_preview_to_program, or edit scenes offline, when unsure. Preview scenes cannot go live directly.

**Scope:** `scenes:golive` (Switch scenes on air) · **MCP tool:** `go_live_scene` · **Notes:** destructive

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |
| `transition` | body | `morph`, `fade`, `slide`, `zoom`, `cut` | optional | One-time transition override for this switch only |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>/golive" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "transition": "morph" }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}/golive`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ transition: "morph" }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create preview of a scene

```http Endpoint
POST /api/v1/overlays/{overlayId}/scenes/{sceneId}/preview
```

Creates an offline preview copy of a scene. Edit it safely (set_scene_member_state), then publish it with take_preview_to_program. Nothing changes on air.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `preview_scene`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>/preview" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}/preview`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Take preview to program

```http Endpoint
POST /api/v1/overlays/{overlayId}/scenes/{sceneId}/take
```

ON AIR when the target scene is live: copies a preview scene into the scene it previews and removes the preview. If the target scene is live, viewers see the change immediately.

**Scope:** `scenes:golive` (Switch scenes on air) · **MCP tool:** `take_preview_to_program` · **Notes:** destructive

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | The PREVIEW scene id. At least 1 |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>/take" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}/take`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Set a layer's state in a scene

```http Endpoint
PATCH /api/v1/overlays/{overlayId}/scenes/{sceneId}/members/{memberId}
```

Sets position, stacking and visibility of one layer inside one scene. For a scene that is NOT live this is an offline edit; for the live scene it changes the stream output immediately.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `set_scene_member_state`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `sceneId` | path | integer | required | Scene id (from list_scenes). At least 1 |
| `memberId` | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
| `layout` | body | object | optional | Placement in design-space pixels (canvas 1920 wide): x/y move the layer from the canvas center, scale 0.05-4, rot in degrees, opacity 0-1, optional crop (cropL/cropT/cropR/cropB in native px) |
| `z` | body | integer | optional | Stacking position (0 = bottom); other layers move to fill the gap. 0 to 1000 |
| `hidden` | body | boolean | optional | Hide or show the layer (on the live output when this overlay is on air) |
| `expectedRev` | body | integer | optional | Optional guard: the scene rev (offline scene) or overlay rev (live scene) you last saw. At least 0 |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/<sceneId>/members/<memberId>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "layout": {}, "z": 1 }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const sceneId = '<sceneId>';
const memberId = '<memberId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/${sceneId}/members/${memberId}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ layout: {}, z: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Reorder scenes

```http Endpoint
PUT /api/v1/overlays/{overlayId}/scenes/order
```

Sets the order of the scenes of an overlay (scene tabs, deck buttons and every scene list follow it). order must contain every scene id of the overlay exactly once, previews included; the first id becomes the first (leftmost) tab. Nothing changes on air.

**Scope:** `scenes:write` (Edit scenes) · **MCP tool:** `reorder_scenes`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `order` | body | array of integer | required | All scene ids of the overlay in the new order (from list_scenes). Up to 100 items |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/overlays/<overlayId>/scenes/order" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "order": [] }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/scenes/order`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ order: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::
