# Live streams and ingest

A **live stream** is a standing channel you create once and reuse for every broadcast from one place, for example one per venue, one per church campus or one per pitch. Its ingest address and key stay the same from show to show, so the crew sets up the encoder once.

```http
POST /v1/streams/live_streams
Idempotency-Key: venue-kasarani-1
```

Every body field is optional.

| Field | Default | What it does |
|---|---|---|
| `latency_mode` | `low` | `low` keeps the picture close to real time. `standard` trades some delay for a steadier picture. |
| `reconnect_window` | `60` | Seconds the broadcast stays open after the encoder drops, from 0 to 1800. See [going live](https://docs.vabu.live/guides/streams/going-live.md#what-happens-if-the-connection-drops). |
| `audio_only` | `false` | A stream with sound and no picture, for radio sets and audiences on small data plans. |
| `playback_policy` | `signed` | `signed` needs a playback link that Vabu issues to a viewer with access. `public` plays for anyone who has the link. See [signed playback](https://docs.vabu.live/concepts/signed-playback.md). |
| `simulcast_targets` | none | Up to 6 other platforms to forward the broadcast to. |
| `external_id` | none | Your own id for the venue. Unique per account and environment. Fetch it back with `GET /v1/streams/live_streams?external_id=...`. |
| `metadata` | none | Your own key and value pairs. Filter lists with `metadata[key]=value`. |

The response holds the stream's `id` (starts `ls_`), its `status`, its `ingest` details and its `playback_ids`.

## Ingest

The `ingest` object says where an encoder sends video.

| Field | Protocol | Use it for |
|---|---|---|
| `rtmp_url` with `stream_key` | RTMP over TLS | OBS, hardware encoders and most phone apps. This is the usual choice. |
| `rtmp_backup_url` | RTMP | A second address for the same stream, for an encoder that can switch. |
| `srt_url` | SRT | Poor or long-distance networks. It recovers lost packets better than RTMP. `srt_passphrase` is set when one is needed. |
| `whip_url` | WHIP | Sending from a browser or a WebRTC tool. It is `null` when the video network behind your account does not offer it. |

The full address for most encoders is the `rtmp_url`, a slash and the `stream_key`. The stream key is a secret. It is encrypted at rest and is never put in an event or a webhook payload. If it leaks, call `POST /v1/streams/live_streams/{id}/reset_stream_key`. The new key works at once and the old one stops.

When a field is `null`, the thing is not offered for that stream. Check the field instead of assuming. [Delivery networks and capabilities](https://docs.vabu.live/concepts/delivery-networks.md) lists the checks.

## Encoder settings

Use H.264 video and AAC audio, a keyframe every 2 seconds and about 2 to 6 Mbps for 720p. The full table, with OBS and phone steps, is in [going live](https://docs.vabu.live/guides/streams/going-live.md).

## Status

`status` follows the encoder.

| Status | Meaning |
|---|---|
| `idle` | No broadcast is running. |
| `connecting` | An encoder has connected and the first video is arriving. |
| `active` | Video is flowing. Viewers can watch. |
| `disconnected` | The encoder dropped. The broadcast is still open for the `reconnect_window`. |
| `disabled` | You switched the stream off. It refuses encoders and viewers. |

Each change produces an event, so you do not need to poll. See [stream events](https://docs.vabu.live/concepts/stream-events.md).

## Control the stream

| Call | What it does |
|---|---|
| `PATCH /v1/streams/live_streams/{id}` | Change `latency_mode`, `reconnect_window`, `metadata` or `external_id`. |
| `POST /v1/streams/live_streams/{id}/disable` | Refuse the encoder and new viewers. Use it to lock a stream between shows. |
| `POST /v1/streams/live_streams/{id}/enable` | Let the stream take video again. |
| `POST /v1/streams/live_streams/{id}/complete` | End the broadcast now, without waiting for the reconnect window. |
| `DELETE /v1/streams/live_streams/{id}` | Delete the stream. Later reads return `404`. |

## Simulcast targets

A simulcast target forwards your broadcast to another platform at the same time. A common use is to send the first part of a show to a free social platform with a link to watch the rest in your app.

```http
POST /v1/streams/live_streams/{id}/simulcast_targets

{ "url": "rtmps://live.example.com/app", "stream_key": "..." }
```

The target's key is stored encrypted and never returned. `DELETE /v1/streams/live_streams/{id}/simulcast_targets/{target_id}` removes it. A target that the video network rejects is listed with `status: "errored"`, and the stream is still created.

## Test mode

A test key makes a simulated stream. It stays `idle` and takes no video. Use it to build your flow, then switch to live keys to send real video. See [test mode](https://docs.vabu.live/concepts/test-mode.md).
