# Monitor channels and live streams

> Follow a YouTube, Twitch or Kick channel and get clips from every live stream or new video, without sending a link.

A monitor watches a channel and clips on its own. There are two types:

| `type` | What it clips | Where the clips appear | Billing |
|---|---|---|---|
| `live` | Every broadcast, while it is on air, in 10-minute blocks | `GET /monitors/{id}/broadcasts/{broadcastId}/clips` | Per 10-minute block that generated clips, only while the monitor is on |
| `video` | Every new video published on the channel | Regular submissions in `GET /clips` | Like a normal clipping |

Platforms: YouTube, Twitch and Kick.

## Create the monitor

```bash
curl -X POST https://api.cut.pro/api/v1/monitors \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "https://www.twitch.tv/gaules",
    "type": "live",
    "template_id": "7398110254410021"
  }'
```

```json title="201 Created"
{
  "id": "7413020011876610",
  "type": "live",
  "platform": "twitch",
  "username": "gaules",
  "display_name": "Gaules",
  "avatar_url": "https://...",
  "enabled": true,
  "enabled_at": "2026-10-29T19:00:00.000Z",
  "strategy_id": "7398110000000001",
  "template_id": "7398110254410021",
  "video_min_duration": null,
  "video_max_duration": null,
  "days_of_week": [],
  "hours_of_day": []
}
```

| Field | Description |
|---|---|
| `channel` | Channel URL: `https://www.youtube.com/@handle`, `https://www.twitch.tv/login` or `https://kick.com/slug`. |
| `type` | `live` or `video`. |
| `enabled` | Starts on (`true`, default). Send `false` to configure now and turn it on later. |
| `template_id` | Template applied to every clip. With it, each clip already arrives with `edit_id`, ready to render or post. |
| `strategy_id` | Clipping strategy. Without it, the default configuration. |

For `video` only:

| Field | Description |
|---|---|
| `video_min_duration`, `video_max_duration` | Ignores shorter or longer videos, in seconds (1 to 3600). |
| `days_of_week` | Accepted days, 0 is Sunday. Empty accepts all. |
| `hours_of_day` | Accepted hour ranges `[from, to]`, in the workspace owner's time zone. |

`POST /monitors` accepts 10 calls per minute, because it queries the channel on the platform. Monitoring the same channel with the same `type` twice returns `409 ALREADY_MONITORING`.

## Turn on and off

```bash
curl -X POST https://api.cut.pro/api/v1/monitors/7413020011876610/start \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

- **Turn on** (`/start`): on a channel that is already live, recording starts in about a minute. Only what goes on air from then on is clipped.
- **Turn off** (`/stop`): no new block is clipped or charged, and the recording in progress stops in about a minute.
- Calling `/start` on a monitor that is on, or `/stop` on one that is off, changes nothing and responds `200`.

> The monitor must stay on for at least 10 minutes before turning off. Before that, `/stop` responds `409 MINIMUM_MONITORING_TIME` with `extra.remaining_seconds`. The monitor also turns off by itself when the balance runs out.

For a channel that streams 24 hours, create it with `enabled: false` and use `/start` and `/stop` at the times you care about.

## Get the clips of a live stream

List the channel's broadcasts:

```bash
curl https://api.cut.pro/api/v1/monitors/7413020011876610/broadcasts \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

```json title="200 OK"
{
  "broadcasts": [
    {
      "id": "318274651093",
      "title": "Championship final",
      "category": "Counter-Strike",
      "language": "pt",
      "is_mature": false,
      "tags": ["Português"],
      "started_at": "2026-10-29T19:02:11.000Z",
      "ended_at": null,
      "clips_count": 14,
      "thumbnail_url": "https://...",
      "recording_expired": false
    }
  ],
  "pagination": { "current_page": 1, "total_pages": 1, "total_count": 1, "has_next_page": false, "has_previous_page": false, "limit": 20 }
}
```

`ended_at: null` means the live stream is on air and keeps generating clips every 10 minutes. Do not wait for it to end: fetch the clips as they arrive.

```bash
curl "https://api.cut.pro/api/v1/monitors/7413020011876610/broadcasts/318274651093/clips?min_rating=7" \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

Each clip carries `rating`, `duration`, `started_at` and `ended_at` (when the moment went on air), `play_url` and:

| Field | Means |
|---|---|
| `edit_id` | The clip already has an edit. Send it to `POST /renders` or `POST /posts`. |
| `render_id` | A finished MP4 of this edit already exists. Download it at `GET /renders/{renderId}/download`. |
| `rendering` | A render of this clip is queued or running. |

A clip without `edit_id` renders with the default layout:

```bash
curl -X POST https://api.cut.pro/api/v1/monitors/7413020011876610/broadcasts/318274651093/clips/7413020199001234/render \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

To bulk edit the clips that have already arrived, use `POST /monitors/{id}/broadcasts/{broadcastId}/clips/apply_template`. For every future clip, put `template_id` on the monitor.

When the recording expires, `recording_expired` becomes `true` and that live stream's clips respond `410 RECORDING_EXPIRED`.

## Manage

| Route | What it does |
|---|---|
| `GET /monitors` | Lists the monitors, filtering by `type`. |
| `GET /monitors/{id}` | Shows one monitor and whether it is on. |
| `PATCH /monitors/{id}` | Changes only the fields sent. `null` clears `template_id` and the duration limits. |
| `DELETE /monitors/{id}` | Stops watching. The clips stay. Creating the same channel and `type` again brings the monitor back, with the same `id` and history. |

## Errors

| Code | When |
|---|---|
| `INVALID_CHANNEL_URL` | The URL is not a YouTube, Twitch or Kick channel. |
| `CREATOR_NOT_FOUND` | The channel does not exist. |
| `LIVE_CLIPS_NOT_AVAILABLE` | The plan does not include live clips. |
| `INVALID_OBSERVING_TYPE` | Asked for broadcasts from a `video` monitor. |
| `MINIMUM_MONITORING_TIME` | Tried to turn off before 10 minutes. |
