# Stream API

Stream title, category and live status on Twitch and Kick.

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 |
| --- | --- | --- |
| [Get stream info](#get-stream-info) | `GET /overlays/{overlayId}/stream-info` | `overlays:read` |
| [Change stream info](#change-stream-info) | `PUT /overlays/{overlayId}/stream-info` | `stream:write` |
| [Get output status](#get-output-status) | `GET /overlays/{overlayId}/output-status` | `overlays:read` |
| [List stream activity](#list-stream-activity) | `GET /overlays/{overlayId}/activity` | `overlays:read` |
| [Check overlay health](#check-overlay-health) | `GET /overlays/{overlayId}/health` | `overlays:read` |
| [Check platform connections](#check-platform-connections) | `GET /status/platforms` | `account:read` |
| [Check OBS](#check-obs) | `GET /status/obs` | `overlays:read` |
| [Get channel info](#get-channel-info) | `GET /stream/{platform}` | `account:read` |
| [Change channel info](#change-channel-info) | `PUT /stream/{platform}` | `stream:write` |
| [Search stream categories](#search-stream-categories) | `GET /stream/{platform}/categories` | `account:read` |

## Operations

### Get stream info

```http Endpoint
GET /api/v1/overlays/{overlayId}/stream-info
```

Returns the title and category of the Twitch channel connected to the overlay owner's account (connected:false when no Twitch channel is connected).

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

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

### Change stream info

```http Endpoint
PUT /api/v1/overlays/{overlayId}/stream-info
```

PUBLIC: changes the title and/or category of the connected Twitch channel right away (viewers and the directory see it). category is the category name, e.g. "Just Chatting"; an unknown name is rejected.

**Scope:** `stream:write` (Change stream info) · **MCP tool:** `set_stream_info`

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `title` | body | string | optional | New stream title. Up to 140 characters |
| `category` | body | string | optional | Twitch category name. Up to 100 characters |

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

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

### Get output status

```http Endpoint
GET /api/v1/overlays/{overlayId}/output-status
```

Tells whether OBS (or a browser) loaded the overlay recently (obsSeenAt, browserSeenAt) and whether the owner's channel is live. checkedAt is the server time, so you can say how long ago OBS was seen. stream.connected is false when no Twitch or Kick account is connected; live:false then means unknown, not offline.

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

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

### List stream activity

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

Lists the latest stream events of the overlay owner's channel (follows, subs, cheers, raids, tips, redemptions, hype trains), newest first. Names and messages come from viewers.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `overlayId` | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
| `limit` | query | integer | optional | How many events (default 10). 1 to 25 |
| `kind` | query | `all`, `follow`, `sub`, `cheer`, `raid`, `tip`, `redemption`, `hype` | optional |  |

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

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

### Check overlay health

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

Diagnoses one overlay: whether OBS or a browser loaded it recently (output.status in_obs, obs_earlier, browser_only, never_loaded), widget errors the running output reported (widgets.layers with state ready, updating, delayed or failed and an error text), the alert box layers and when a test alert was last sent, plus a list of issues. Parts the server cannot see say status unknown with a reason.

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

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

### Check platform connections

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

Diagnoses your Twitch, Kick and YouTube connections: connected and healthy, missing permissions (missingScopes; reconnect to grant them), the EventSub or webhook subscriptions that deliver alerts, and the latest stream events per platform (type and time only). Parts the server cannot see say status unknown with a reason.

**Scope:** `account:read` (Read your account) · **MCP tool:** `get_platform_status` · **Notes:** read only

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

### Check OBS

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

Tells which of your overlays OBS loaded and when (overlays sorted by obsSeenAt, inObs means within the last 12 hours, lastLoaded is the most recent one), and for your own overlays the last scene name OBS reported for scene sync. The OBS WebSocket connection runs in your browser, so its state is unknown to the server.

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

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

### Get channel info

```http Endpoint
GET /api/v1/stream/{platform}
```

Returns the stream title and category of your connected Twitch or Kick channel and whether PX Studio may change them (canEdit). connected:false when that platform is not connected.

**Scope:** `account:read` (Read your account) · **MCP tool:** `get_channel_info` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | `twitch`, `kick` | required | Twitch or kick |

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

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

### Change channel info

```http Endpoint
PUT /api/v1/stream/{platform}
```

PUBLIC: changes the title and/or category of your connected Twitch or Kick channel right away (viewers and the directory see it). category is the category name (search_stream_categories).

**Scope:** `stream:write` (Change stream info) · **MCP tool:** `set_channel_info` · **Notes:** needs confirmation in MCP

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | `twitch`, `kick` | required | Twitch or kick |
| `title` | body | string | optional | Up to 140 characters |
| `category` | body | string | optional | Up to 100 characters |

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

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

### Search stream categories

```http Endpoint
GET /api/v1/stream/{platform}/categories
```

Searches the categories (games) of Twitch or Kick by name, e.g. to pick the exact name for set_channel_info or an automation.

**Scope:** `account:read` (Read your account) · **MCP tool:** `search_stream_categories` · **Notes:** read only

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | `twitch`, `kick` | required | Twitch or kick |
| `q` | query | string | optional | Up to 100 characters |

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

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