Skip to main content

Streaming API Reference

Complete API reference for livestreaming functionality in Spritz.

Base URL​

https://app.spritz.chat/api/streams

Authentication​

All endpoints require authentication unless otherwise noted. Include credentials in fetch requests:

const response = await fetch("https://app.spritz.chat/api/streams", {
credentials: "include", // Required for session cookies
headers: {
"Content-Type": "application/json",
},
});

See API Introduction for complete authentication setup.

Endpoints​

List Streams​

GET /api/streams?userAddress=0x...&live=true&limit=20

Query Parameters:

  • userAddress (optional): Filter by user address
  • live (optional): Filter to only live streams (true/false)
  • limit (optional): Maximum results (default: 20)

Response:

{
"streams": [
{
"id": "uuid",
"user_address": "0x...",
"stream_id": "livepeer-stream-id",
"stream_key": "stream-key",
"playback_id": "playback-id",
"title": "My Stream",
"description": "Stream description",
"status": "live",
"viewer_count": 5,
"started_at": "2026-01-15T14:30:00Z",
"ended_at": null,
"created_at": "2026-01-15T14:30:00Z",
"playback_url": "https://livepeercdn.studio/hls/{id}/index.m3u8"
}
]
}

Create Stream​

POST /api/streams

Request Body:

{
"userAddress": "0x...",
"title": "My Stream",
"description": "Optional description"
}

Response:

{
"stream": {
"id": "uuid",
"stream_id": "livepeer-stream-id",
"stream_key": "stream-key",
"playback_id": "playback-id",
"rtmp_url": "rtmp://rtmp.livepeer.com/live/{key}",
"playback_url": "https://livepeercdn.studio/hls/{id}/index.m3u8",
"status": "idle"
}
}

Get Stream​

GET /api/streams/:id

Response:

{
"stream": {
"id": "uuid",
"user_address": "0x...",
"stream_id": "livepeer-stream-id",
"playback_id": "playback-id",
"title": "Stream Title",
"status": "live",
"viewer_count": 10,
"playback_url": "...",
"started_at": "2026-01-15T14:30:00Z"
}
}

Delete Stream​

DELETE /api/streams/:id

Response:

{
"success": true
}

Get Stream Assets (Recordings)​

GET /api/streams/:id/assets?refresh=true

Query Parameters:

  • refresh (optional): If true, fetches assets from Livepeer and updates the database before returning.

Response:

{
"assets": [
{
"id": "asset-id",
"playback_id": "playback-id",
"playback_url": "https://livepeercdn.studio/hls/{id}/index.m3u8",
"download_url": "https://livepeer.studio/api/asset/{id}/download",
"status": {
"phase": "ready",
"progress": 100
},
"duration_seconds": 1234,
"size_bytes": 12345678,
"created_at": "2026-01-15T14:30:00Z"
}
]
}

Refresh Stream Assets​

POST /api/streams/:id/assets

Refreshes recording assets from Livepeer and upserts them into the database. Use after a stream ends to pull the latest VOD status and URLs.

Get Stream Chat​

GET /api/streams/:id/chat?limit=50

Response:

{
"messages": [
{
"id": "uuid",
"user_address": "0x...",
"content": "Hello!",
"created_at": "2026-01-15T14:30:00Z"
}
]
}

Send Stream Chat Message​

POST /api/streams/:id/chat

Request Body:

{
"userAddress": "0x...",
"message": "Hello stream!"
}

Increment Viewer Count​

POST /api/streams/:id/viewers

Request Body: Optional (not required in app; viewer is inferred from session).

Query (optional): ?action=leave — Use with navigator.sendBeacon() on page unload to decrement viewer count without a separate DELETE.

Decrement Viewer Count​

DELETE /api/streams/:id/viewers

Decrements viewer count when a viewer leaves the stream page.

Public Endpoints​

Get Public Stream Info​

GET /api/public/streams/:id

No authentication required. Returns public stream information. Live status is verified with Livepeer using the stream's stream_id (not playback_id).

Response:

{
"stream": {
"id": "uuid",
"title": "Stream Title",
"description": "Stream description",
"status": "live",
"is_live": true,
"playback_url": "https://livepeercdn.studio/hls/{playbackId}/index.m3u8",
"started_at": "2026-01-15T14:30:00Z",
"ended_at": null,
"viewer_count": 10,
"streamer": {
"address": "0x...",
"display_name": "Display Name",
"avatar_url": "https://..."
}
}
}

Join Public Stream​

POST /api/public/streams/:id

Increments viewer count for public access.

Query (optional): ?action=leave — Use with sendBeacon on page unload to decrement viewer count in one request instead of DELETE.

Leave Public Stream​

DELETE /api/public/streams/:id

Decrements viewer count.

Error Responses​

400 Bad Request​

{
"error": "User address is required"
}

404 Not Found​

{
"error": "Stream not found"
}

500 Internal Server Error​

{
"error": "Failed to create stream on Livepeer"
}

Stream States​

  • idle: Stream created but not started
  • live: Currently broadcasting
  • ended: Stream has ended

Technical Details​

WebRTC Ingestion​

Streams use WebRTC via WHIP protocol:

  • Ingest URL: https://livepeer.studio/webrtc/{streamKey}
  • Protocol: WHIP (WebRTC-HTTP Ingestion Protocol)
  • Resolution: 1080x1920 (9:16 portrait)

HLS Playback​

Viewers receive HLS streams:

  • Playback URL: https://livepeercdn.studio/hls/{playbackId}/index.m3u8
  • Protocol: HLS (HTTP Live Streaming)
  • Adaptive: Automatically adjusts quality

Recording​

Streams are automatically recorded:

  • Format: HLS
  • Storage: Livepeer
  • Processing: May take a few minutes after stream ends

Best Practices​

  1. Error Handling: Always handle stream creation errors
  2. Viewer Tracking: Properly increment/decrement viewer counts
  3. Cleanup: Delete unused streams
  4. Status Checks: Verify stream status before operations
  5. Rate Limiting: Respect API rate limits

Next Steps​