guides

Set YouTube broadcast settings from your app

A YouTube destination can carry a broadcast template — the settings TRaX stamps on the broadcast it auto-creates for you at go-live: title, privacy, latency, DVR, and the handful of YouTube switches that are only settable through the API. This guide is how a mobile client reads and writes that template over /v1, so the app can offer the same broadcast controls the studio does.

Which host. These endpoints are on dev only for now: https://api-dev.traxstreaming.live/v1 with a dev key. This page will say so when they reach production.

The one field

The template rides on the destination as broadcastConfig. You set it when you create a destination:

POST /v1/studios/{studioId}/destinations
Authorization: Bearer sk_live_…
Content-Type: application/json

{
  "name": "YouTube main",
  "platform": "youtube",
  "connectionId": "…",
  "broadcastConfig": {
    "mode": "create",
    "title": "Tonight's show",
    "privacy": "unlisted",
    "latency": "low",
    "autoStart": true,
    "autoStop": true,
    "dvr": true,
    "madeForKids": false
  }
}

…or change it later without touching anything else on the destination:

PATCH /v1/studios/{studioId}/destinations/{destinationId}
Authorization: Bearer sk_live_…
Content-Type: application/json

{ "broadcastConfig": { "mode": "create", "title": "New title", "privacy": "public" } }

Both need the destinations:write scope — the same scope that creates the destination. A broadcastConfig on a non-YouTube destination is stored and ignored; only YouTube reads it at go-live.

The fields

Field What it sets
mode create = auto-create a fresh broadcast at go-live from this template. pick = you chose a specific existing broadcast; auto-create is off.
title Title stamped on the auto-created broadcast.
privacy public, unlisted, or private. There is no members-only — YouTube's live API does not expose it.
description Broadcast description body.
latency normal, low, or ultraLow. ultraLow disables closed captions and caps resolution at 1080p.
autoStart / autoStop The broadcast goes live / stops automatically with your ingest.
dvr Viewers can rewind the live stream.
madeForKids The COPPA "made for kids" self-declaration.
enableEmbed May the watch page be embedded off YouTube.
recordFromStart Archive records from the first frame.
enableMonitorStream The preview/monitor stream that parks the broadcast in "testing" before it goes live.
streamDelayMs Intentional broadcast delay, in milliseconds. 0 = none.
projection rectangular or 360.

Two rules worth knowing

Tri-state fields. enableEmbed, recordFromStart, and enableMonitorStream are three-way: send true, send false, or omit the key entirely to leave it unset. Omitting means YouTube applies its own default — and omitting enableMonitorStream specifically preserves the standard behaviour where an auto-starting broadcast goes straight to live instead of parking in "testing". Set enableMonitorStream: true under autoStart only if you deliberately want that testing hold.

Immutable once live. YouTube freezes most of the broadcast body (embed, DVR, record-from-start, monitor stream, delay, projection) the moment the broadcast enters testing or live. Edit the template while you are off air; a change sent after go-live applies to the next broadcast, not the running one.

Round-trip

A read of the destination shows the template back to you (the stream key is never returned):

GET /v1/studios/{studioId}/destinations

The broadcastConfig you get back is exactly what a future go-live will use. Omitted tri-state fields stay omitted — the read never invents a false you did not send.

Work with broadcasts directly (#665)

The template above tells go-live what to create. Three more endpoints let your app skip the template entirely and deal in actual YouTube broadcasts — the same three moves the studio's Stream Setup panel makes.

List what you can pick from

GET /v1/studios/{studioId}/destinations/{destinationId}/broadcasts

Requires destinations:read. Returns the destination's platform-side broadcasts — recent, upcoming and active — each with its id, title, lifecycle status and, on YouTube, the broadcast's live settings (privacy, latency, DVR, …) so an editor can seed from actual values instead of guesses. Platforms with no broadcast concept (Twitch, Kick, Trovo) and pasted-key destinations answer an empty list, not an error.

Create a broadcast now

POST /v1/studios/{studioId}/destinations/{destinationId}/broadcast
Content-Type: application/json

{ "title": "Tonight's show", "description": "…" }

Requires destinations:write. This inserts the broadcast on YouTube immediately — not at go-live — seeded from the destination's saved broadcastConfig (privacy, latency, DVR, contentDetails), with your title/ description overriding the template's copies. Omit scheduledStartTime to start now; pass an RFC 3339 time to schedule it. The created broadcast is adopted as the destination's pick (mode flips to pick), so going live binds the stream to it. 201 returns the broadcast; its id is what the edit, thumbnail and pick endpoints take.

Pick an existing broadcast — or clear the pick

POST /v1/studios/{studioId}/destinations/{destinationId}/broadcast/pick
Content-Type: application/json

{ "broadcastId": "dQw4w9WgXcQ", "title": "Tonight's show" }

Requires destinations:write. Points the destination at one existing broadcast from the list above; go-live then binds the stream to it. Send { "broadcastId": null } to clear the pick — the destination returns to create mode and go-live auto-creates from the template again. This is a pointer write: nothing is validated against YouTube here, so a deleted broadcast id surfaces at go-live, not at pick time.

Rounding out the set, the PATCH …/broadcast edit and the thumbnail upload from the Broadcast Manager wave apply to whichever broadcast id you name — see the API reference for updateDestinationBroadcast and setDestinationBroadcastThumbnail.

Which broadcast am I on? activeBroadcastId

Every one of the calls above takes a broadcast id, and until now there was no supported way to get one for a destination you did not just create. Every destination read now carries it:

GET /v1/studios/{studioId}/destinations
{
  "id": "…",
  "platform": "youtube",
  "activeBroadcastId": "dQw4w9WgXcQ"
}

activeBroadcastId is the broadcast this destination is currently operating on. It is what you pass to PATCH …/broadcast and to the thumbnail upload. It rides the SSE destination event too, so a client watching GET /v1/studios/{studioId}/events learns a new id the moment go-live mints one instead of polling for it.

The field is always present and empty when there is no broadcast: a channel-scoped platform (Twitch, Kick, Trovo) has no broadcast concept at all, a create-mode YouTube destination that has never gone live has nothing yet, and a cleared pick leaves nothing behind.

Two cases, and they do not age the same. Treat this difference as part of the contract, not a detail:

How the id was obtained How long it stays valid
Picked — you called …/broadcast/pick, or created one with POST …/broadcast Stable until the pick changes or is cleared. Names a real broadcast whether or not anything is streaming.
Auto-created — no pick; the destination mints a fresh broadcast at each go-live The one minted for the current or most recent session. Goes stale once that broadcast completes — a completed YouTube broadcast cannot be edited or restreamed, and the next go-live mints a different one.

So: read it again after going live. Do not cache it across sessions and assume an edit will land where you expect — between sessions, a create-mode id can name a broadcast the next go-live will not touch. We would rather ship a field that tells you when not to trust it than one that quietly lies.

Do not read settings

Destinations also carry a settings blob, and the id does appear inside it. That is not a contract. settings is opaque: its schema is not part of this API, we reshape it when the studio needs to, and a client parsing it will break on a release that changes nothing you can see. activeBroadcastId exists precisely so you never have to.

A typical flow, end to end: list the broadcasts you can pick from, pick one or create one now, then read activeBroadcastId off the destination whenever you need to name it again.