Live Streaming
Broadcast live events, church services, classes, sports, and product launches. Ingest with RTMP or SRT from any encoder, then deliver adaptive HLS (and low-latency HLS) to browsers and mobile apps — with optional DVR and VOD archive.
Professional ingest
Push from OBS, vMix, Wirecast, FFmpeg, or hardware encoders over RTMP or SRT.
Adaptive playback
Deliver multi-bitrate HLS and LL-HLS so viewers on 3G and fiber both get a smooth stream.
Massive fan-out
One publisher, unlimited viewers via CDN edge — separate from interactive WebRTC rooms.
DVR & VOD
Optional live DVR window and automatic VOD archive when the stream ends.
Africa-first edge
Ingest and playback POPs optimized for West, East, and Southern African audiences.
Stream webhooks
live.stream.started, live, idle, ended, and recording.ready for automation.
RTMP · SRT
OBS & pro encoders
HLS · LL-HLS
ABR ladder auto-built
~3–8s
LL-HLS target (p95)
100k+
Per stream (plan-based)
Authentication
Authorization: Basic <token>. Auth guide →Rooms vs live streams
Choose your mode
Multi-party calls — hosts and participants publish and subscribe with low latency (telehealth, tutoring, support).
- 2–50 participants
- Bidirectional A/V
- Join tokens + SDK
One-to-many broadcast — encoder pushes RTMP/SRT; thousands of viewers pull HLS or LL-HLS.
- 1 publisher
- Unlimited viewers
- CDN playback URLs
- Your backend creates a stream with
POST /v1/video/streamsand receives ingest credentials + playback URLs. - Encoder (OBS, FFmpeg, camera) pushes media to the RTMP or SRT ingest URL using the stream key.
- Sendexa transcodes an ABR ladder and publishes HLS / LL-HLS manifests on the CDN.
- Viewers play with any HLS player (hls.js, AVPlayer, ExoPlayer) or the Sendexa player embed.
- Webhooks fire when the stream goes live, idles, ends, or when the VOD archive is ready.
Encoder (OBS) Your Backend Sendexa Viewers| | | || | POST /v1/video/streams | || |------------------------>| || | streamId, rtmpUrl, | || | streamKey, hlsUrl | || |<------------------------| || RTMP/SRT push | | ||------------------------------------------------>| ABR + CDN || | |----------------------->|| | webhooks (live/ended) | HLS / LL-HLS pull || |<------------------------| |
Create a live stream
Provision a new broadcast. Response includes ingest endpoints (keep the stream key secret) and public playback URLs for your apps.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | optional | Human-readable title shown in the dashboard and player. |
| latencyMode | "standard" | "low" | optional | standard ≈ 8–15s glass-to-glass (HLS). low enables LL-HLS (~3–8s). Default: standard. |
| dvr | boolean | optional | Enable live rewind window for viewers. Default: false. |
| dvrWindowSeconds | number | optional | DVR buffer length (60–14400). Default: 7200 when dvr=true. |
| record | boolean | optional | Archive to VOD when the stream ends. Default: false. |
| region | string | optional | Preferred ingest region (e.g. af-west, eu-west). Auto if omitted. |
| reconnectWindowSeconds | number | optional | How long to keep the stream 'live' after encoder disconnect (0–600). Default: 60. |
| metadata | object | optional | Arbitrary JSON for your app (eventId, channelSlug, etc.). |
curl -X POST 'https://api.sendexa.co/v1/video/streams' \-H 'Content-Type: application/json' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \-d '{"name": "Sunday Service — Live","latencyMode": "low","dvr": true,"dvrWindowSeconds": 7200,"record": true,"region": "af-west","reconnectWindowSeconds": 120,"metadata": { "eventId": "EVT-2048", "channel": "main-sanctuary" }}'
Success response (201)
{"success": true,"code": "STREAM_CREATED","message": "Live stream created.","requestId": "req_8f2a1c90","data": {"streamId": "str_01JQX7K2M9N4P5","name": "Sunday Service — Live","status": "idle","latencyMode": "low","region": "af-west","dvr": true,"dvrWindowSeconds": 7200,"record": true,"reconnectWindowSeconds": 120,"ingest": {"rtmpUrl": "rtmps://ingest.sendexa.co/live","rtmpUrlInsecure": "rtmp://ingest.sendexa.co/live","streamKey": "sk_live_a1b2c3d4e5f6…","srtUrl": "srt://ingest.sendexa.co:9000?streamid=str_01JQX7K2M9N4P5","server": "ingest.sendexa.co"},"playback": {"hls": "https://live.sendexa.co/str_01JQX7K2M9N4P5/index.m3u8","llHls": "https://live.sendexa.co/str_01JQX7K2M9N4P5/ll/index.m3u8","embedUrl": "https://player.sendexa.co/live/str_01JQX7K2M9N4P5","poster": null},"metadata": { "eventId": "EVT-2048", "channel": "main-sanctuary" },"createdAt": "2026-07-12T18:00:00.000Z","updatedAt": "2026-07-12T18:00:00.000Z"}}
Stream lifecycle
| Status | Meaning | Typical trigger |
|---|---|---|
| idle | Created; waiting for encoder | POST /v1/video/streams |
| starting | First packets received; ladder building | Encoder connects |
| live | Playback manifests ready for viewers | Keyframes + segments ready |
| disconnected | Encoder dropped; reconnect window open | Network blip / stop |
| ended | Stream closed permanently | API end or reconnect timeout |
idle ──push──> starting ──ready──> live ──stop/end──> ended^ || disconnect |+<── disconnected ──+ (within reconnectWindowSeconds)
REST surface
Manage an active stream
Get stream
curl 'https://api.sendexa.co/v1/video/streams/str_01JQX7K2M9N4P5' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN'
End stream (force stop + finalize VOD)
curl -X POST 'https://api.sendexa.co/v1/video/streams/str_01JQX7K2M9N4P5/end' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN' \-H 'Content-Type: application/json' \-d '{ "reason": "scheduled_end" }'
List streams
curl 'https://api.sendexa.co/v1/video/streams?status=live&limit=20' \-H 'Authorization: Basic YOUR_DASHBOARD_BASE64_TOKEN'
Error codes
| Code | HTTP | Meaning |
|---|---|---|
| STREAM_CREATED | 201 | Stream provisioned |
| STREAM_NOT_FOUND | 404 | Unknown streamId |
| STREAM_ALREADY_ENDED | 409 | Cannot end or push to ended stream |
| STREAM_LIMIT_REACHED | 429 | Concurrent live stream quota exceeded |
| INVALID_LATENCY_MODE | 400 | latencyMode must be standard or low |
| INGEST_AUTH_FAILED | 401 | Bad stream key on encoder (ingest plane) |
Next steps
Security
streamKey like a password. Rotate keys from the dashboard if leaked. Prefer rtmps:// over plain RTMP. Playback URLs can be made signed/tokenized for paid events — see Playback docs.