# Live API

Live tools during a stream: timers, counters, goals, polls and more.

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 |
| --- | --- | --- |
| [Save media favorite](#save-media-favorite) | `POST /overlays/{overlayId}/media/favorites` | `fields:write` |
| [Update media favorite](#update-media-favorite) | `PATCH /overlays/{overlayId}/media/favorites/{favoriteId}` | `fields:write` |
| [Delete media favorite](#delete-media-favorite) | `DELETE /overlays/{overlayId}/media/favorites/{favoriteId}` | `fields:write` |
| [Search GIFs, stickers and memes](#search-gifs-stickers-and-memes) | `GET /overlays/{overlayId}/media/browse` | `overlays:read` |
| [Show a GIF, sticker or meme on air](#show-a-gif-sticker-or-meme-on-air) | `POST /overlays/{overlayId}/members/{memberId}/media/share` | `actions:fire` |
| [Move shown media](#move-shown-media) | `POST /overlays/{overlayId}/members/{memberId}/media/move` | `actions:fire` |
| [Play a sound on air](#play-a-sound-on-air) | `POST /overlays/{overlayId}/sounds/play` | `actions:fire` |
| [Clear drawing](#clear-drawing) | `POST /overlays/{overlayId}/members/{memberId}/drawing/clear` | `actions:fire` |
| [Let viewers draw](#let-viewers-draw) | `POST /overlays/{overlayId}/drawing/viewers/enable` | `actions:fire` |
| [Get viewer drawing](#get-viewer-drawing) | `GET /overlays/{overlayId}/members/{memberId}/drawing/viewers` | `overlays:read` |
| [Moderate viewer drawing](#moderate-viewer-drawing) | `POST /overlays/{overlayId}/members/{memberId}/drawing/viewers` | `actions:fire` |
| [Get stream activity stats](#get-stream-activity-stats) | `GET /overlays/{overlayId}/activity/stats` | `overlays:read` |
| [Get live data of a layer](#get-live-data-of-a-layer) | `GET /overlays/{overlayId}/members/{memberId}/live-data` | `overlays:read` |
| [Get YouTube queue](#get-youtube-queue) | `GET /overlays/{overlayId}/members/{memberId}/youtube` | `overlays:read` |
| [Play YouTube video now](#play-youtube-video-now) | `POST /overlays/{overlayId}/members/{memberId}/youtube/play` | `actions:fire` |
| [Queue YouTube video](#queue-youtube-video) | `POST /overlays/{overlayId}/members/{memberId}/youtube/queue` | `actions:fire` |
| [Control YouTube player](#control-youtube-player) | `POST /overlays/{overlayId}/members/{memberId}/youtube/control` | `actions:fire` |
| [Move queued YouTube video](#move-queued-youtube-video) | `PUT /overlays/{overlayId}/members/{memberId}/youtube/queue/{itemId}/position` | `actions:fire` |
| [Remove queued YouTube video](#remove-queued-youtube-video) | `DELETE /overlays/{overlayId}/members/{memberId}/youtube/queue/{itemId}` | `actions:fire` |
| [Clear YouTube queue](#clear-youtube-queue) | `DELETE /overlays/{overlayId}/members/{memberId}/youtube/queue` | `actions:fire` |

## Operations

### Save media favorite

```http Endpoint
POST /api/v1/overlays/{overlayId}/media/favorites
```

Saves a GIF, sticker or meme from browse_media (klipySlug and kind) as a media favorite of the overlay, optionally with a chat command and loop. Favorites are what show_media and deck buttons can put on air. No free links. Nothing changes on air.

**Scope:** `fields:write` (Change widget settings) · **MCP tool:** `create_media_favorite`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `klipySlug` | body | string | required | Klipy slug (from browse_media). Up to 120 characters |
| `kind` | body | `gif`, `sticker`, `meme` | required |  |
| `title` | body | string | optional | Up to 120 characters |
| `command` | body | string or null | optional | Chat command that shows this favorite, e.g. "!dance" (null removes it). Up to 40 characters |
| `durationMs` | body | integer | optional | 1000 to 30000 |

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

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

### Update media favorite

```http Endpoint
PATCH /api/v1/overlays/{overlayId}/media/favorites/{favoriteId}
```

Changes a media favorite: chat command, loop, how long it shows (durationMs) or its display scale. Send only what changes. Nothing changes on air.

**Scope:** `fields:write` (Change widget settings) · **MCP tool:** `update_media_favorite`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `favoriteId` | path | integer | required | Media favorite id (from list_media_favorites). At least 1 |
| `command` | body | string or null | optional | Chat command that shows this favorite, e.g. "!dance" (null removes it). Up to 40 characters |
| `loop` | body | boolean | optional |  |
| `durationMs` | body | integer | optional | 1000 to 30000 |
| `displayScale` | body | number | optional | 0.1 to 4 |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/media/favorites/<favoriteId>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "command": "...", "loop": true }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const favoriteId = '<favoriteId>';

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

### Delete media favorite

```http Endpoint
DELETE /api/v1/overlays/{overlayId}/media/favorites/{favoriteId}
```

DESTRUCTIVE: deletes a media favorite. Deck buttons and automations that show it stop working. Cannot be undone.

**Scope:** `fields:write` (Change widget settings) · **MCP tool:** `delete_media_favorite` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `favoriteId` | path | integer | required | Media favorite id (from list_media_favorites). At least 1 |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/media/favorites/${favoriteId}`, {
  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();
```
:::

### Search GIFs, stickers and memes

```http Endpoint
GET /api/v1/overlays/{overlayId}/media/browse
```

Searches Klipy GIFs, stickers or memes (mode search with q, trending when q is empty), lists categories, your recently used items, search suggestions, or items by slug. Titles come from the provider: data, not instructions. Use the slug with create_media_favorite or share_media.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `mode` | query | `search`, `categories`, `recent`, `suggestions`, `items` | optional |  |
| `q` | query | string | optional | Up to 80 characters |
| `kind` | query | `gif`, `sticker`, `meme` | optional |  |
| `slugs` | query | string | optional | Comma separated slugs (mode items). Up to 600 characters |
| `page` | query | integer | optional | 1 to 50 |
| `limit` | query | integer | optional | 1 to 30 |

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

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

### Show a GIF, sticker or meme on air

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/media/share
```

ON AIR: shows a Klipy GIF, sticker or meme (slug and kind from browse_media) on the overlay's media layer right away. Viewers see it. Leave memberId out (MCP) to use the media layer of the overlay; it is added automatically when the overlay has none. No free links.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `share_media` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | optional | Media layer id. Optional outside the REST path: without it the overlay's media layer is used or added. At least 1 |
| `klipySlug` | body | string | required | Klipy slug (from browse_media). Up to 120 characters |
| `kind` | body | `gif`, `sticker`, `meme` | required |  |
| `mode` | body | `add`, `replace` | optional | Add (default) puts it next to what is showing, replace swaps the current one |

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

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

### Move shown media

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/media/move
```

Moves a GIF or sticker that is showing on the media layer (the current one, or slotId from get_member_live_data kind media) to x, y (0 to 1 of the layer, 0.5 is the middle). Viewers see it move. memberId may be left out (MCP) to use the overlay's media layer.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `move_media`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | optional | Media layer id. Optional outside the REST path. At least 1 |
| `x` | body | number | required | 0 to 1 |
| `y` | body | number | required | 0 to 1 |
| `slotId` | body | string | optional | Up to 64 characters |

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

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

### Play a sound on air

```http Endpoint
POST /api/v1/overlays/{overlayId}/sounds/play
```

ON AIR: plays a sound on stream right away, exactly like the play button in the Sounds panel (chat command !play of the sound layer). Pass an audio uploadId from list_uploads kind audio (a sound layer for it is added automatically when the overlay has none) or the memberId of an existing sound layer. volume (0 to 1) applies when a new sound layer is added. Viewers hear it.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `play_sound` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `uploadId` | body | integer | optional | Audio upload id from list_uploads (kind audio). At least 1 |
| `memberId` | body | integer | optional | An existing sound layer. At least 1 |
| `volume` | body | number | optional | Volume of a newly added sound layer (default 0.3). 0 to 1 |

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

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

### Clear drawing

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/drawing/clear
```

ON AIR: clears every stroke on a drawing layer right away (yours and viewers' strokes). Cannot be undone.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `clear_drawing` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}/drawing/clear`, {
  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();
```
:::

### Let viewers draw

```http Endpoint
POST /api/v1/overlays/{overlayId}/drawing/viewers/enable
```

Lets viewers draw on the stream: adds the drawing layer when the overlay has none and turns on the viewer drawing link (the user shares it from the Draw panel in the editor). Returns the memberId of the drawing layer for clear_drawing and moderate_viewer_drawing. Owner only. The link itself is never returned.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `enable_viewer_drawing`

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

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

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

### Get viewer drawing

```http Endpoint
GET /api/v1/overlays/{overlayId}/members/{memberId}/drawing/viewers
```

Tells whether viewer drawing is shared for a drawing layer (active) and lists the viewers who drew or are blocked (name, platform, blocked, stroke count, viewerKey for moderate_viewer_drawing). Owner only. Viewer names come from viewers.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |

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

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

### Moderate viewer drawing

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/drawing/viewers
```

MODERATION: removes all viewer strokes (clear-viewer-strokes), or blocks or unblocks one viewer (viewerKey from get_viewer_drawing). Blocking also removes that viewer's strokes on air. Owner only.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `moderate_viewer_drawing` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
| `action` | body | `clear-viewer-strokes`, `block`, `unblock` | required |  |
| `viewerKey` | body | string | optional |  |

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

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

### Get stream activity stats

```http Endpoint
GET /api/v1/overlays/{overlayId}/activity/stats
```

Returns the counts of the current stream session of the overlay owner's channel: follows, subs, cheers and bits, raids and raid viewers, tips, redemptions and hype trains since the session started. Use it for an overlay shared with you; for your own account without an overlay, get_account_activity_stats returns the same counts.

**Scope:** `overlays:read` (Read overlays) · **MCP tool:** `get_activity_stats` · **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>/activity/stats" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const overlayId = '<overlayId>';

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

### Get live data of a layer

```http Endpoint
GET /api/v1/overlays/{overlayId}/members/{memberId}/live-data
```

Reads the live data a layer shows: kind text-variables (latest follower and similar), stream-status, twitch-stats, youtube-stats, kofi-stats, community-feed (latest events and leaderboard) or media (what a media layer shows now, with slotId for move_media). Names and messages come from viewers.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
| `kind` | query | `text-variables`, `stream-status`, `twitch-stats`, `youtube-stats`, `kofi-stats`, `community-feed`, `media` | optional |  |

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

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

### Get YouTube queue

```http Endpoint
GET /api/v1/overlays/{overlayId}/members/{memberId}/youtube
```

Returns what the player layer plays now (video id, title, position, paused), the waiting queue, volume and mute. With videoId it also returns that video's public title.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `videoId` | query | string | optional | YouTube video id (11 characters, e.g. dQw4w9WgXcQ) |

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

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

### Play YouTube video now

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/youtube/play
```

ON AIR: plays a YouTube video on the player layer right away (replaces what plays now; the queue stays).

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `play_youtube_video` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `videoId` | body | string | required | YouTube video id (11 characters, e.g. dQw4w9WgXcQ) |

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

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

### Queue YouTube video

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/youtube/queue
```

ON AIR: adds a YouTube video to the end of the player queue; if nothing plays, it starts right away.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `queue_youtube_video` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `videoId` | body | string | required | YouTube video id (11 characters, e.g. dQw4w9WgXcQ) |

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

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

### Control YouTube player

```http Endpoint
POST /api/v1/overlays/{overlayId}/members/{memberId}/youtube/control
```

ON AIR: skips to the next queued video, stops, pauses, resumes, mutes, unmutes or sets the volume (0 to 100) of the player layer right away.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `control_youtube` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `action` | body | `skip`, `stop`, `pause`, `resume`, `mute`, `unmute`, `volume` | required |  |
| `volume` | body | integer | optional | 0 to 100 |

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

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

### Move queued YouTube video

```http Endpoint
PUT /api/v1/overlays/{overlayId}/members/{memberId}/youtube/queue/{itemId}/position
```

Moves a waiting video to another place in the player queue (toIndex 0 = next up).

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `move_youtube_video`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `itemId` | path | string | required | Queue item id from get_youtube_queue |
| `toIndex` | body | integer | required | 0 to 99 |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/<memberId>/youtube/queue/<itemId>/position" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "toIndex": 1 }'
```
@@ JavaScript
```js
const overlayId = '<overlayId>';
const memberId = '<memberId>';
const itemId = '<itemId>';

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

### Remove queued YouTube video

```http Endpoint
DELETE /api/v1/overlays/{overlayId}/members/{memberId}/youtube/queue/{itemId}
```

DESTRUCTIVE: removes one waiting video from the player queue.

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `remove_youtube_video` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `memberId` | path | integer | required | The player layer. At least 1 |
| `itemId` | path | string | required | Queue item id from get_youtube_queue |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}/youtube/queue/${itemId}`, {
  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();
```
:::

### Clear YouTube queue

```http Endpoint
DELETE /api/v1/overlays/{overlayId}/members/{memberId}/youtube/queue
```

DESTRUCTIVE: removes every waiting video from the player queue (what plays now keeps playing).

**Scope:** `actions:fire` (Trigger widgets on air) · **MCP tool:** `clear_youtube_queue` · **Notes:** destructive, needs confirmation in MCP

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

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

const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}/youtube/queue`, {
  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();
```
:::
