Live Streams API
Stream live from OBS, ffmpeg or a browser. CDNShark takes your RTMP or WebRTC feed, turns it into HLS and delivers it through the CDN to any number of viewers. Creating a stream needs a plan that includes Live.
How it works
| You get | Example | Who sees it |
|---|---|---|
rtmp_url | rtmp://ingest01.cdnshark.com/live | Your encoder's Server field. |
stream_key | lvab12cd34ef56gh78ij?key=K7mP… | Your encoder's Stream key field. Secret: anyone with it can broadcast on your stream. |
playback_id | lvab12cd34ef56gh78ij | Public. It names the stream in playback URLs. |
hls_playback_url | https://live-show-x1y2z3.cdn.cdnshark.com/live/lvab12cd34ef56gh78ij.m3u8 | Public. Give it to your player and your viewers. |
The stream key is the playback id plus ?key= and a secret. Paste it into the encoder as one value. The secret never appears in a playback URL, so sharing the player link is safe.
Create a stream
POST /api/live/streams (streams:write)
| Field | Required | Notes |
|---|---|---|
name | yes | Up to 120 characters. |
archive_on_end | no | Reserved. Recording ended streams is not available yet. |
curl -X POST https://cdnshark.com/api/live/streams \
-H "Authorization: Bearer YOUR_TOKEN" -H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name": "Friday show"}'
{
"id": 16, "name": "Friday show", "slug": "friday-show-x1y2z3",
"stream_key": "lvab12cd34ef56gh78ij?key=K7mP...",
"playback_id": "lvab12cd34ef56gh78ij",
"rtmp_url": "rtmp://ingest01.cdnshark.com/live",
"status": "idle"
}
Fetch hls_playback_url with the get call below. Its CDN hostname is ready within a few seconds.
Go live
OBS: Settings, Stream, Service Custom. Set Server to rtmp_url and Stream Key to stream_key. Recommended: H.264 video, AAC audio, keyframe interval 2 seconds.
ffmpeg:
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -g 60 -c:a aac \
-f flv "rtmp://ingest01.cdnshark.com/live/lvab12cd34ef56gh78ij?key=K7mP..."
Browser (WebRTC, WHIP): publish to https://{ingest host}/rtc/v1/whip/?app=live&stream={playback_id}&key={secret}. The ingest host is the host in rtmp_url. WebRTC media uses UDP port 8000.
A wrong or old key is refused when the encoder connects. When the feed starts, status becomes live and the live.stream.started webhook fires. When it stops, the stream returns to idle and live.stream.ended fires. Viewers are typically 10 to 20 seconds behind the encoder.
Play it on your site
<video id="player" controls autoplay muted playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
const url = 'https://live-show-x1y2z3.cdn.cdnshark.com/live/lvab12cd34ef56gh78ij.m3u8';
const video = document.getElementById('player');
if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = url; } // Safari
else if (Hls.isSupported()) { const hls = new Hls(); hls.loadSource(url); hls.attachMedia(video); }
</script>
Any HLS player works (hls.js, Video.js, native Safari and iOS). Before the stream is live, the playlist returns 404: show a "starting soon" message and retry.
Endpoints
| Method | Path | Permission | What it does |
|---|---|---|---|
| GET | /api/live/streams | streams:read | All your streams (an array): id, name, slug, status, playback_id, rtmp_url, hls_playback_url, current_viewers, went_live_at, archive_on_end, created_at. Never the key. |
| POST | /api/live/streams | streams:write | Create (above). |
| GET | /api/live/streams/{id} | streams:read | One stream, including stream_key and hls_playback_url. |
| POST | /api/live/streams/{id}/rotate-key | streams:write | New secret. Returns {"stream_key", "playback_id", "hls_playback_url"}. The playback URL does not change, so embeds keep working. Update your encoder with the new key. A broadcast already running is not cut off. |
| DELETE | /api/live/streams/{id} | streams:write | Deletes the stream and its CDN hostname. |