API reference
Streams
Programmatic control of AI-hosted live streams.
| Method | Path | Scope |
|---|---|---|
POST | /api/v1/streams | streams:write |
GET | /api/v1/streams | streams:read |
GET | /api/v1/streams/{id} | streams:read |
DELETE | /api/v1/streams/{id} | streams:write |
Stream lifecycle
preparing → live → ended
↘ error
Preparing streams that can't dispatch within 5 minutes automatically transition
to error. `preparing` time never consumes plan minutes.
| Status | Meaning | Fields populated |
|---|---|---|
preparing | Stream created, agent is being dispatched to the room. | stream_id, room_name, created_at |
live | Avatar is streaming to the platform. From here a live-key stream counts its full booked duration_minutes against your plan. | + started_at, viewer_count (live-updating) |
ended | Stream finished (via DELETE, the agent, or the platform). Ending early does not give booked minutes back. | + ended_at, final viewer_count |
error | Something failed during dispatch or streaming. See the status field for details. | + ended_at |
Stuck preparing: if the agent worker can't join within 5 minutes, the stream transitions to
errorand astream.errorwebhook fires (if registered).preparingtime never consumes plan minutes.
Start a stream
POST /api/v1/streams
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
creator_id | string | ✅ | Creator to host (use GET /api/v1/creators to list available creators). |
product_name | string | ✅ | Product/game being featured. |
platform | string | ✅ | youtube, tiktok, twitch, facebook, instagram. |
duration_minutes | number | ✅ live / – test | How long to stream (1–480 minutes). Required for live keys. Once the stream goes live, this booked duration is what counts against your plan minutes, even if you end it early. Omit with test keys — they return live immediately. |
script | string | – | Talking points / script seed for the host. |
vertical | string | – | Must match your brand's configured vertical. |
Response 201 Created
{
"stream_id": "a1b2c3d4-e5f6-…", // ← save this — you'll need it to poll/end
"status": "live",
"room_name": "stream-a1b2c3d4",
"ws_url": "wss://rt.twintone.ai/v1/rooms/stream-a1b2c3d4",
"viewer_token": null,
"created_at": "2026-08-07T10:00:00.000Z"
}
statusmatches the stream's stored status: a live-key stream isliveonce the agent has been dispatched, andstream.startedfires at the same moment.Test keys: with
tt_test_…the stream also returnsstatus: "live"(plus"test": true,ws_url: null) — no agent dispatch, no minutes consumed — so you can build the full lifecycle integration, includingDELETE, without a real stream.No connected channel: a live-key stream for a brand with no connected channel that has a stream key still starts, but reaches no platform. The
201response then includes"warnings": [{ "code": "no_broadcast_destination", "message": "…" }]. Connect a channel and start a new stream.
Errors: 400 missing_fields · 400 invalid_fields · 400 invalid_creator · 401 unauthorized ·
402 plan_required · 402 no_minutes · 403 vertical_mismatch · 429 rate_limited · 429 concurrency_limit · 502 launch_failed
List streams
GET /api/v1/streams?status=live&limit=20&offset=0
| Param | Default | Notes |
|---|---|---|
status | all | Filter: preparing, live, ended, error. |
limit | 20 | Max 100. |
offset | 0 | For pagination. |
Response 200
{
"streams": [ { "id": "…", "status": "live", "platform": "youtube", … } ],
"total": 47,
"limit": 20,
"offset": 0
}
Results are newest-first and scoped to your brand. With a test key, only
streams started with a test key are listed, and total counts only those.
Get a stream
GET /api/v1/streams/{id}
Response 200
{
"stream_id": "a1b2c3d4-…",
"status": "live",
"creator_id": "avt_9ww075quzedr", // ← the creator you picked
"product_name": "Radiance Serum", // ← YOUR product name
"platform": "youtube",
"vertical": "live-commerce",
"viewer_count": 312,
"started_at": "2026-08-07T10:00:14.000Z",
"ended_at": null,
"room_name": "stream-a1b2c3d4",
"events": []
}
404 if the stream doesn't exist or belongs to another brand. A test key
also gets 404 for a stream that wasn't started with a test key.
Note: the
eventsfield is currently empty (reserved for future telemetry events).
End a stream
DELETE /api/v1/streams/{id}
Ends a live stream immediately. For a live-key stream this stops the
broadcast on every platform first, then marks the stream ended. Test-key
streams have no broadcast, so they are just marked ended.
Response 200
{ "stream_id": "a1b2c3d4-…", "status": "ended", "ended_at": "2026-08-07T11:30:00.000Z" }
404 if the stream isn't found or isn't live. A test key can only end
streams started with a test key, so it gets 404 for any other stream and
that stream keeps running.
502 stop_failed if we couldn't confirm the broadcast stopped. The stream
stays live; retry the request.
Was this page helpful?