# Bot API

PXStudioBot: commands, timers, loyalty, giveaways, song requests and moderation.

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 bot commands](#list-bot-commands) | `GET /bot/commands` | `bot:read` |
| [Create bot command](#create-bot-command) | `POST /bot/commands` | `bot:write` |
| [Update bot command](#update-bot-command) | `PATCH /bot/commands/{commandId}` | `bot:write` |
| [Delete bot command](#delete-bot-command) | `DELETE /bot/commands/{commandId}` | `bot:write` |
| [Get song queue](#get-song-queue) | `GET /bot/songs` | `bot:read` |
| [Skip, pause or resume songs](#skip-pause-or-resume-songs) | `POST /bot/songs/control` | `bot:write` |
| [Set song volume](#set-song-volume) | `PUT /bot/songs/volume` | `bot:write` |
| [Remove song request](#remove-song-request) | `DELETE /bot/songs/{requestId}` | `bot:write` |
| [Clear song queue](#clear-song-queue) | `DELETE /bot/songs` | `bot:write` |
| [Get bot status](#get-bot-status) | `GET /bot/status` | `bot:read` |
| [Switch the bot on or off for a platform](#switch-the-bot-on-or-off-for-a-platform) | `PUT /bot/platforms/{platform}` | `bot:write` |
| [Set bot language](#set-bot-language) | `PUT /bot/language` | `bot:write` |
| [Get bot settings](#get-bot-settings) | `GET /bot/settings` | `bot:read` |
| [Update bot settings](#update-bot-settings) | `PATCH /bot/settings` | `bot:write` |
| [Get bot system messages](#get-bot-system-messages) | `GET /bot/system-messages` | `bot:read` |
| [Update bot system messages](#update-bot-system-messages) | `PATCH /bot/system-messages` | `bot:write` |
| [Switch bot command on or off](#switch-bot-command-on-or-off) | `PUT /bot/commands/{commandId}/enabled` | `bot:write` |
| [Export bot commands](#export-bot-commands) | `GET /bot/commands/export` | `bot:read` |
| [Import bot commands](#import-bot-commands) | `POST /bot/commands/import` | `bot:write` |
| [Replace all bot commands](#replace-all-bot-commands) | `POST /bot/commands/replace` | `bot:write` |
| [Switch built-in command on or off](#switch-built-in-command-on-or-off) | `PUT /bot/builtins/{name}` | `bot:write` |
| [List bot timers](#list-bot-timers) | `GET /bot/timers` | `bot:read` |
| [Create bot timer](#create-bot-timer) | `POST /bot/timers` | `bot:write` |
| [Update bot timer](#update-bot-timer) | `PATCH /bot/timers/{timerId}` | `bot:write` |
| [Delete bot timer](#delete-bot-timer) | `DELETE /bot/timers/{timerId}` | `bot:write` |
| [List bot counters](#list-bot-counters) | `GET /bot/counters` | `bot:read` |
| [Create bot counter](#create-bot-counter) | `POST /bot/counters` | `bot:write` |
| [Update bot counter](#update-bot-counter) | `PATCH /bot/counters/{counterId}` | `bot:write` |
| [Delete bot counter](#delete-bot-counter) | `DELETE /bot/counters/{counterId}` | `bot:write` |
| [List bot quotes](#list-bot-quotes) | `GET /bot/quotes` | `bot:read` |
| [Add bot quote](#add-bot-quote) | `POST /bot/quotes` | `bot:write` |
| [Delete bot quote](#delete-bot-quote) | `DELETE /bot/quotes/{quoteId}` | `bot:write` |
| [List custom APIs](#list-custom-apis) | `GET /bot/custom-apis` | `bot:read` |
| [Create custom API](#create-custom-api) | `POST /bot/custom-apis` | `bot:write` |
| [Update custom API](#update-custom-api) | `PATCH /bot/custom-apis/{apiId}` | `bot:write` |
| [Delete custom API](#delete-custom-api) | `DELETE /bot/custom-apis/{apiId}` | `bot:write` |
| [Get bot moderation](#get-bot-moderation) | `GET /bot/moderation` | `bot:read` |
| [Update bot moderation](#update-bot-moderation) | `PATCH /bot/moderation` | `bot:write` |
| [Update song request settings](#update-song-request-settings) | `PATCH /bot/songs/settings` | `bot:write` |
| [Move song request](#move-song-request) | `PUT /bot/songs/{requestId}/position` | `bot:write` |

## Operations

### List bot commands

```http Endpoint
GET /api/v1/bot/commands
```

Lists your PXStudioBot chat commands with all their settings and which built-in commands are switched off.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `list_bot_commands` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/commands" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/commands', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create bot command

```http Endpoint
POST /api/v1/bot/commands
```

Creates a PXStudioBot chat command (live in chat right away) with every field of the bot editor: reply, alternative replies, aliases, trigger, reply mode, lowest role, cooldowns, platforms, on/off and an optional action (fire a widget command on a layer, put a scene on air, move a layer into a spot). Action targets are layers (overlayId + memberId).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `create_bot_command`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | required | Command name without the "!" prefix, e.g. "discord" (lowercase letters, digits, underscore). Up to 40 characters |
| `response` | body | string | optional | The text the bot replies with (up to 400 characters). Placeholders like {user} or {count:name} work. Up to 400 characters |
| `responsePool` | body | array of string | optional | Alternative replies; the bot picks one at random. Up to 10 items |
| `aliases` | body | array of string | optional | Other names for the same command. Up to 10 items |
| `triggerType` | body | `command`, `keyword`, `regex` | optional | Command = !name, keyword = a word anywhere in a message, regex = a pattern |
| `pattern` | body | string | optional | Keyword or regular expression for keyword/regex triggers. Up to 200 characters |
| `replyMode` | body | `channel`, `reply`, `whisper`, `silent` | optional | Where the reply goes; silent runs only the action |
| `minRole` | body | `everyone`, `sub`, `vip`, `mod`, `broadcaster` | optional | Lowest role allowed (everyone, sub, vip, mod, broadcaster) |
| `cooldownGlobalS` | body | integer | optional | 0 to 3600 |
| `cooldownUserS` | body | integer | optional | 0 to 3600 |
| `modsBypassCooldown` | body | boolean | optional |  |
| `platforms` | body | array of `twitch`, `kick`, `youtube` | optional | Platforms; an empty list means all platforms. Up to 3 items |
| `enabled` | body | boolean | optional | False keeps the command switched off |
| `action` | body | object | optional |  |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/commands" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "..." }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/commands', {
  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();
```
:::

### Update bot command

```http Endpoint
PATCH /api/v1/bot/commands/{commandId}
```

Changes a PXStudioBot command: send only the fields to change (same fields as create_bot_command; action type none removes the action). Live in chat right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_command`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `commandId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | optional | Command name without the "!" prefix, e.g. "discord" (lowercase letters, digits, underscore). Up to 40 characters |
| `response` | body | string | optional | The text the bot replies with (up to 400 characters). Placeholders like {user} or {count:name} work. Up to 400 characters |
| `responsePool` | body | array of string | optional | Alternative replies; the bot picks one at random. Up to 10 items |
| `aliases` | body | array of string | optional | Other names for the same command. Up to 10 items |
| `triggerType` | body | `command`, `keyword`, `regex` | optional | Command = !name, keyword = a word anywhere in a message, regex = a pattern |
| `pattern` | body | string | optional | Keyword or regular expression for keyword/regex triggers. Up to 200 characters |
| `replyMode` | body | `channel`, `reply`, `whisper`, `silent` | optional | Where the reply goes; silent runs only the action |
| `minRole` | body | `everyone`, `sub`, `vip`, `mod`, `broadcaster` | optional | Lowest role allowed (everyone, sub, vip, mod, broadcaster) |
| `cooldownGlobalS` | body | integer | optional | 0 to 3600 |
| `cooldownUserS` | body | integer | optional | 0 to 3600 |
| `modsBypassCooldown` | body | boolean | optional |  |
| `platforms` | body | array of `twitch`, `kick`, `youtube` | optional | Platforms; an empty list means all platforms. Up to 3 items |
| `enabled` | body | boolean | optional | False keeps the command switched off |
| `action` | body | object | optional |  |

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

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

### Delete bot command

```http Endpoint
DELETE /api/v1/bot/commands/{commandId}
```

DESTRUCTIVE: deletes a PXStudioBot command.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `delete_bot_command` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `commandId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/commands/${commandId}`, {
  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();
```
:::

### Get song queue

```http Endpoint
GET /api/v1/bot/songs
```

Returns the PXStudioBot song requests: whether they are switched on, the song playing now, the waiting queue, pause state and volume. Song titles and requester names come from viewers.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `get_song_queue` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/songs" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/songs', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Skip, pause or resume songs

```http Endpoint
POST /api/v1/bot/songs/control
```

ON AIR: skips the current song request, pauses or resumes song playback for your stream right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `control_songs` · **Notes:** destructive

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `action` | body | `skip`, `pause`, `resume` | required |  |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/songs/control" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "action": "skip" }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/songs/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();
```
:::

### Set song volume

```http Endpoint
PUT /api/v1/bot/songs/volume
```

Sets the playback volume of song requests (0 to 100).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `set_song_volume`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `volume` | body | integer | required | 0 to 100 |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/bot/songs/volume" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "volume": 1 }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/songs/volume', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ volume: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Remove song request

```http Endpoint
DELETE /api/v1/bot/songs/{requestId}
```

DESTRUCTIVE: removes one song request from the queue (requestId from get_song_queue).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `remove_song_request` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `requestId` | path | integer | required | Song request id from get_song_queue. At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/songs/${requestId}`, {
  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 song queue

```http Endpoint
DELETE /api/v1/bot/songs
```

DESTRUCTIVE: removes every waiting song request from the queue.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `clear_song_queue` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X DELETE "https://pxstudio.cloud/api/v1/bot/songs" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/songs', {
  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();
```
:::

### Get bot status

```http Endpoint
GET /api/v1/bot/status
```

Returns whether PXStudioBot is connected and active on Twitch, Kick and YouTube, whether a platform needs a reconnect, and chat stats (messages today and in 7 days, commands).

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `get_bot_status` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/status" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/status', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Switch the bot on or off for a platform

```http Endpoint
PUT /api/v1/bot/platforms/{platform}
```

PUBLIC: lets PXStudioBot join (active: true) or leave (active: false) your own chat on Twitch, Kick or YouTube. Only for your own account; connecting a platform happens in the app settings.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `set_bot_platform_active` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | `twitch`, `kick`, `youtube` | required |  |
| `active` | body | boolean | required |  |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/bot/platforms/<platform>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'
```
@@ JavaScript
```js
const platform = '<platform>';

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

### Set bot language

```http Endpoint
PUT /api/v1/bot/language
```

PUBLIC: sets the language of the PXStudioBot built-in chat replies (en or de); inherit follows your studio language. Only for your own account.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `set_bot_language` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `locale` | body | `en`, `de`, `inherit` | required |  |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/bot/language" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "locale": "en" }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/language', {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ locale: "en" }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Get bot settings

```http Endpoint
GET /api/v1/bot/settings
```

Returns the PXStudioBot settings: deny feedback, chat command editing (!cmd), quotes from chat, and (for your own bot) the bot language.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `get_bot_settings` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/settings" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/settings', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update bot settings

```http Endpoint
PATCH /api/v1/bot/settings
```

PUBLIC: changes PXStudioBot settings (send only what changes): deny feedback in chat, chat command editing (!cmd) and quotes from chat. Viewers notice it right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_settings` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `denyFeedback` | body | boolean | optional | The bot tells viewers when they may not use a command |
| `chatCrudEnabled` | body | boolean | optional | Mods can add, edit and delete commands from chat (!cmd) |
| `quoteChatEnabled` | body | boolean | optional | Viewers can read and mods can add quotes from chat (!quote) |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/settings" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "denyFeedback": true, "chatCrudEnabled": true }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/settings', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ denyFeedback: true, chatCrudEnabled: true }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Get bot system messages

```http Endpoint
GET /api/v1/bot/system-messages
```

Lists the built-in PXStudioBot chat messages (giveaway, loyalty, songs and more) with the default text, your own text and whether each is on. Filter with group.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `get_bot_system_messages` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `group` | query | `builtin`, `giveaway`, `loyalty`, `songs`, `youtube`, `feedback`, `cmd`, `quote` | optional | Only messages of this group |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/system-messages" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/system-messages', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update bot system messages

```http Endpoint
PATCH /api/v1/bot/system-messages
```

PUBLIC: changes built-in PXStudioBot chat messages (1 to 20 at once): text sets your own text, enabled false switches a message off, reset goes back to the default. Other messages stay as they are.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_system_messages` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `changes` | body | array of object | required | Up to 20 items |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/system-messages" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "changes": [] }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/system-messages', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ changes: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Switch bot command on or off

```http Endpoint
PUT /api/v1/bot/commands/{commandId}/enabled
```

PUBLIC: switches a PXStudioBot command on or off; viewers can use it (or not) in chat right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `set_bot_command_enabled` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `commandId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `enabled` | body | boolean | required |  |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/bot/commands/<commandId>/enabled" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
```
@@ JavaScript
```js
const commandId = '<commandId>';

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

### Export bot commands

```http Endpoint
GET /api/v1/bot/commands/export
```

Exports all PXStudioBot commands in the form import_bot_commands takes (actions point to layers; an action whose layer you cannot see is marked actionTarget.unattached, and import keeps the saved action for it).

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `export_bot_commands` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/commands/export" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/commands/export', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Import bot commands

```http Endpoint
POST /api/v1/bot/commands/import
```

PUBLIC: imports PXStudioBot commands (1 to 50). A command with an existing name is updated, a new name is created; all are live in chat right away. Other commands stay.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `import_bot_commands` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `commands` | body | array of object | required | Commands in the same form as create_bot_command (and export_bot_commands). Up to 50 items |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/commands/import" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "commands": [] }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/commands/import', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ commands: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Replace all bot commands

```http Endpoint
POST /api/v1/bot/commands/replace
```

DESTRUCTIVE: replaces ALL your PXStudioBot commands with the given list (1 to 50): every other command is deleted. Switched-off built-in commands stay switched off.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `replace_bot_commands` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `commands` | body | array of object | required | Commands in the same form as create_bot_command (and export_bot_commands). Up to 50 items |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/commands/replace" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "commands": [] }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/commands/replace', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ commands: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Switch built-in command on or off

```http Endpoint
PUT /api/v1/bot/builtins/{name}
```

PUBLIC: switches a built-in PXStudioBot command (like !uptime or !points) on or off in chat right away. If you have your own command with that name, change that one instead.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `set_builtin_command_enabled` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `name` | path | `commands`, `uptime`, `title`, `game`, `so`, `followage`, `giveaway`, `join`, `claim`, `odds`, `points`, `top`, `redeem`, `link`, `slots`, `gamble`, `give`, `transfer`, `loan`, `borrow`, `sr`, `song`, `queue`, `skip`, `voteskip`, `wrongsong`, `cmd`, `quote`, `quotes` | required |  |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `enabled` | body | boolean | required |  |

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

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

### List bot timers

```http Endpoint
GET /api/v1/bot/timers
```

Lists your PXStudioBot timers (messages or commands the bot posts every few minutes).

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `list_bot_timers` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/timers" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/timers', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create bot timer

```http Endpoint
POST /api/v1/bot/timers
```

PUBLIC: creates a PXStudioBot timer that posts a message (or runs a bot command) in your chat every intervalMin minutes.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `create_bot_timer` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | required | Name of the timer (only you see it). Up to 64 characters |
| `message` | body | string | optional | Text the bot posts every interval. Up to 400 characters |
| `commandName` | body | string | optional | Instead of a text: run this bot command every interval. Up to 32 characters |
| `intervalMin` | body | integer | required | Minutes between posts. 2 to 1440 |
| `minMessages` | body | integer | optional | Chat messages needed since the last post (0 = always post). 0 to 1000 |
| `liveOnly` | body | boolean | optional | Only post while you are live |
| `platforms` | body | array of `twitch`, `kick`, `youtube` | optional | Platforms; an empty list means all platforms. Up to 3 items |
| `enabled` | body | boolean | optional |  |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/timers" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "...", "intervalMin": 2 }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/timers', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: "...", intervalMin: 2 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update bot timer

```http Endpoint
PATCH /api/v1/bot/timers/{timerId}
```

PUBLIC: changes a PXStudioBot timer (send only what changes; enabled alone switches it on or off). It posts with the new settings right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_timer` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `timerId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | optional | Name of the timer (only you see it). Up to 64 characters |
| `message` | body | string | optional | Text the bot posts every interval. Up to 400 characters |
| `commandName` | body | string | optional | Instead of a text: run this bot command every interval. Up to 32 characters |
| `intervalMin` | body | integer | optional | Minutes between posts. 2 to 1440 |
| `minMessages` | body | integer | optional | Chat messages needed since the last post (0 = always post). 0 to 1000 |
| `liveOnly` | body | boolean | optional | Only post while you are live |
| `platforms` | body | array of `twitch`, `kick`, `youtube` | optional | Platforms; an empty list means all platforms. Up to 3 items |
| `enabled` | body | boolean | optional |  |

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

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

### Delete bot timer

```http Endpoint
DELETE /api/v1/bot/timers/{timerId}
```

DESTRUCTIVE: deletes a PXStudioBot timer.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `delete_bot_timer` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `timerId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/timers/${timerId}`, {
  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();
```
:::

### List bot counters

```http Endpoint
GET /api/v1/bot/counters
```

Lists your PXStudioBot counters (chat variables like {count:deaths}) with their values.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `list_bot_counters` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/counters" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/counters', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create bot counter

```http Endpoint
POST /api/v1/bot/counters
```

Creates a PXStudioBot counter (use it in replies as {count:name}).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `create_bot_counter`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | required | Lowercase letters, digits and underscore, without "!". Up to 32 characters |
| `value` | body | integer | optional | -1000000000 to 1000000000 |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/counters" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "..." }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/counters', {
  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();
```
:::

### Update bot counter

```http Endpoint
PATCH /api/v1/bot/counters/{counterId}
```

Changes a PXStudioBot counter: delta adds (or subtracts) to the value, value sets it, name renames it. Send value or delta, not both.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_counter`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `counterId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | optional | Lowercase letters, digits and underscore, without "!". Up to 32 characters |
| `value` | body | integer | optional | -1000000000 to 1000000000 |
| `delta` | body | integer | optional | -1000 to 1000 |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/counters/<counterId>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "...", "value": 1 }'
```
@@ JavaScript
```js
const counterId = '<counterId>';

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

### Delete bot counter

```http Endpoint
DELETE /api/v1/bot/counters/{counterId}
```

DESTRUCTIVE: deletes a PXStudioBot counter and its value.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `delete_bot_counter` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `counterId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/counters/${counterId}`, {
  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();
```
:::

### List bot quotes

```http Endpoint
GET /api/v1/bot/quotes
```

Lists your PXStudioBot quotes (newest first), optionally filtered by text.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `list_bot_quotes` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `q` | query | string | optional | Only quotes containing this text. Up to 100 characters |
| `quoteId` | query | integer | optional | Only this quote. At least 1 |
| `limit` | query | integer | optional | 1 to 50 |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/quotes" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/quotes', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Add bot quote

```http Endpoint
POST /api/v1/bot/quotes
```

Adds a quote to your PXStudioBot quotes (viewers read them with !quote).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `add_bot_quote`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `text` | body | string | required | Up to 500 characters |
| `author` | body | string | optional | Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/quotes" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "text": "..." }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/quotes', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ text: "..." }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Delete bot quote

```http Endpoint
DELETE /api/v1/bot/quotes/{quoteId}
```

DESTRUCTIVE: deletes a PXStudioBot quote.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `delete_bot_quote` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `quoteId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/quotes/${quoteId}`, {
  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();
```
:::

### List custom APIs

```http Endpoint
GET /api/v1/bot/custom-apis
```

Lists the custom APIs your PXStudioBot replies can use ({api:name}). Header values and URL query values stay hidden.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `list_custom_apis` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/custom-apis" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/custom-apis', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Create custom API

```http Endpoint
POST /api/v1/bot/custom-apis
```

EXTERNAL: adds a custom API the server calls (GET over https) when a bot reply uses {api:name}. Header values (keys) are only set in the Bot desk.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `create_custom_api` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | required | Name used in replies as {api:name}. Up to 32 characters |
| `urlTemplate` | body | string | required | Https URL the server calls; placeholders like {user} or {query} work. Private and local hosts are refused. Up to 500 characters |
| `responsePath` | body | string | optional | Dot path into the JSON answer, e.g. data.0.title (empty = whole text). Up to 200 characters |
| `cacheS` | body | integer | optional | Seconds to reuse an answer. 0 to 3600 |
| `enabled` | body | boolean | optional |  |

::: tabs
@@ cURL
```bash
curl -X POST "https://pxstudio.cloud/api/v1/bot/custom-apis" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "...", "urlTemplate": "..." }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/custom-apis', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: "...", urlTemplate: "..." }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update custom API

```http Endpoint
PATCH /api/v1/bot/custom-apis/{apiId}
```

EXTERNAL: changes a custom API (send only what changes). Saved header values stay with the same host and are only changed in the Bot desk. A new urlTemplate on another host is refused while header values are saved (ui_only), unless dropHeaders is true: then the saved header values are deleted and never reach the new host.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_custom_api` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `apiId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `name` | body | string | optional | Name used in replies as {api:name}. Up to 32 characters |
| `urlTemplate` | body | string | optional | Https URL the server calls; placeholders like {user} or {query} work. Private and local hosts are refused. Up to 500 characters |
| `responsePath` | body | string | optional | Dot path into the JSON answer, e.g. data.0.title (empty = whole text). Up to 200 characters |
| `cacheS` | body | integer | optional | Seconds to reuse an answer. 0 to 3600 |
| `enabled` | body | boolean | optional |  |
| `dropHeaders` | body | boolean | optional | True deletes the saved header values (needed to move a custom API with header values to another host) |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/custom-apis/<apiId>" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "...", "urlTemplate": "..." }'
```
@@ JavaScript
```js
const apiId = '<apiId>';

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

### Delete custom API

```http Endpoint
DELETE /api/v1/bot/custom-apis/{apiId}
```

DESTRUCTIVE: deletes a custom API; replies that use {api:name} show nothing for it.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `delete_custom_api` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `apiId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

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

const res = await fetch(`https://pxstudio.cloud/api/v1/bot/custom-apis/${apiId}`, {
  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();
```
:::

### Get bot moderation

```http Endpoint
GET /api/v1/bot/moderation
```

Returns the PXStudioBot chat filters (banned words, links, caps, emotes, symbols, repetition, message length, first messages), strike escalation, exempt roles and the viewer whitelist.

**Scope:** `bot:read` (Read bot settings) · **MCP tool:** `get_bot_moderation` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |

::: tabs
@@ cURL
```bash
curl -X GET "https://pxstudio.cloud/api/v1/bot/moderation" \
  -H "Authorization: Bearer $PX_TOKEN"
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/moderation', {
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
  },
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update bot moderation

```http Endpoint
PATCH /api/v1/bot/moderation
```

MODERATION: changes PXStudioBot chat filters (send only what changes; lists replace the old list). The bot deletes, warns, times out or bans viewers by the new rules right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_bot_moderation` · **Notes:** destructive, needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `exemptRoles` | body | object | optional | Roles the filters skip |
| `whitelist` | body | array of string | optional | Viewer logins the filters skip (replaces the list). Up to 100 items |
| `strikes` | body | object | optional |  |
| `filters` | body | object | optional |  |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/moderation" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "exemptRoles": {}, "whitelist": [] }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/moderation', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ exemptRoles: {}, whitelist: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Update song request settings

```http Endpoint
PATCH /api/v1/bot/songs/settings
```

PUBLIC: changes the song request rules (send only what changes): on/off for viewers, longest song, songs per viewer, subs only, point cost, vote skip and blocked videos. Viewers notice it in chat right away.

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `update_song_settings` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `enabled` | body | boolean | optional | Viewers can request songs with !sr |
| `maxDurationS` | body | integer | optional | Longest allowed song in seconds (0 = no limit). 0 to 36000 |
| `maxPerUser` | body | integer | optional | Songs one viewer may have in the queue. 1 to 20 |
| `subOnly` | body | boolean | optional |  |
| `loyaltyCost` | body | integer | optional | Loyalty points a request costs (0 = free). 0 to 1000000000 |
| `voteSkipThreshold` | body | integer | optional | Votes needed for !voteskip. 1 to 1000 |
| `blacklist` | body | array of string | optional | Blocked YouTube video ids (replaces the list). Up to 500 items |

::: tabs
@@ cURL
```bash
curl -X PATCH "https://pxstudio.cloud/api/v1/bot/songs/settings" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "maxDurationS": 1 }'
```
@@ JavaScript
```js
const res = await fetch('https://pxstudio.cloud/api/v1/bot/songs/settings', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.PX_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ enabled: true, maxDurationS: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();
```
:::

### Move song request

```http Endpoint
PUT /api/v1/bot/songs/{requestId}/position
```

Moves one waiting song request one place up or down in the queue (position counts from 0).

**Scope:** `bot:write` (Change the bot) · **MCP tool:** `move_song_request`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `requestId` | path | integer | required | At least 1 |
| `overlayId` | query | string | optional | Act on the bot of this overlay's owner. Only for overlays shared with you; leave out for your own bot. Up to 64 characters |
| `direction` | body | `up`, `down` | required |  |

::: tabs
@@ cURL
```bash
curl -X PUT "https://pxstudio.cloud/api/v1/bot/songs/<requestId>/position" \
  -H "Authorization: Bearer $PX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "direction": "up" }'
```
@@ JavaScript
```js
const requestId = '<requestId>';

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