Streams
Streams are the core resource of the Live Streaming API. A stream has a lifecycle — created offline, pushed live via RTMPS, then ended. Each stream is backed by a Cloudflare Live input and returns an HLS playback URL for viewers.
Create a stream
POST /api/v1/streams/
Creates a new livestream and provisions a Cloudflare Live ingest input. Returns RTMPS credentials for your broadcasting software.
Auth required: Yes
Rate limit: 10 requests per minute
A user can only have one active (live) stream at a time. Creating a second stream while one is active returns 400.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Stream title |
description | string | No | Stream description |
category_id | UUID | No | Category to browse under |
thumbnail_url | string | No | Thumbnail image URL |
{
"title": "Building a REST API in 60 minutes",
"description": "Live coding session — FastAPI from scratch",
"category_id": "7a2f3c80-e11b-4d8a-9e3c-1f2a3b4c5d6e"
}
Response
Returns a StreamWithIngestResponse including private ingest credentials.
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Building a REST API in 60 minutes",
"description": "Live coding session — FastAPI from scratch",
"status": "offline",
"viewer_count": 0,
"playback_url": "https://customer-xyz.cloudflarestream.com/abc123/manifest/video.m3u8",
"thumbnail_url": null,
"started_at": null,
"created_at": "2026-04-25T10:00:00Z",
"ingest": {
"rtmps_url": "rtmps://live.cloudflare.com:443/live/",
"stream_key": "your-stream-key-here"
}
}
Configure OBS: Settings → Stream → Custom, set Server to rtmps_url and Stream Key to stream_key.
List streams
GET /api/v1/streams/
Browse and discover livestreams. Live streams appear first, sorted by viewer count. Ended streams follow, sorted by most recent.
Auth required: No (optional — authenticated users may see additional metadata)
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status_filter | string | — | Filter: live, ended, or all |
category_id | UUID | — | Filter by category |
user_id | UUID | — | Filter streams from a specific user |
search | string | — | Search in title and description |
tenant_id | UUID | — | Filter by organization (multi-tenant scoping) |
page | integer | 1 | Page number |
per_page | integer | 20 | Results per page (max 100) |
# Get all live streams in the "Technology" category
GET /api/v1/streams/?status_filter=live&category_id=7a2f3c80-...&per_page=20
Response
{
"streams": [
{
"id": "a1b2c3d4-...",
"title": "Building a REST API in 60 minutes",
"status": "live",
"viewer_count": 142,
"playback_url": "https://customer-xyz.cloudflarestream.com/abc123/manifest/video.m3u8",
"thumbnail_url": "https://...",
"started_at": "2026-04-25T10:05:00Z",
"streamer": {
"id": "...",
"username": "alice",
"display_name": "Alice Chen",
"avatar_url": "https://...",
"follower_count": 1523,
"is_verified": false
}
}
],
"total": 47,
"page": 1,
"per_page": 20,
"has_more": true
}
Get stream details
GET /api/v1/streams/id/{stream_id}
Get full details for a specific stream. If the authenticated user is the stream owner, the response includes ingest credentials (rtmps_url, stream_key).
Auth required: No (owner auth reveals ingest info)
Path parameters
| Parameter | Type | Description |
|---|---|---|
stream_id | UUID | The stream ID |
GET /api/v1/streams/id/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer $API_KEY
Update stream
PATCH /api/v1/streams/id/{stream_id}
PUT /api/v1/streams/id/{stream_id}
Update stream title, description, category, or thumbnail. Owner only. Both PUT and PATCH are supported.
Auth required: Yes (owner only)
Request body
All fields are optional — include only what you want to change.
| Field | Type | Description |
|---|---|---|
title | string | Stream title |
description | string | Stream description |
category_id | UUID | Category ID |
thumbnail_url | string | Thumbnail URL |
Delete stream
DELETE /api/v1/streams/id/{stream_id}
Permanently delete a stream and its associated Cloudflare Live input. Owner only.
Auth required: Yes (owner only)
Returns 204 No Content on success.
Start stream
POST /api/v1/streams/id/{id}/start
Manually transition a stream from offline to live. Sets started_at to the current timestamp.
Auth required: Yes (owner only)
Returns 400 if the stream is already live or has ended. Ended streams cannot be restarted — create a new stream instead.
End stream
POST /api/v1/streams/{stream_id}/end
Manually end a live stream. Sets status to ended and records the end time.
Auth required: Yes (owner only)
Returns 400 if the stream is already ended.
Regenerate stream key
POST /api/v1/streams/{stream_id}/regenerate-key
Generate a new stream key and RTMPS URL. Immediately invalidates the previous key. Use this if your stream key is compromised.
Auth required: Yes (owner only)
Response
{
"rtmps_url": "rtmps://live.cloudflare.com:443/live/",
"stream_key": "new-stream-key-abc123"
}
Get user streams
GET /api/v1/streams/users/{username}/streams
List all streams from a specific user. Public endpoint.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status_filter | string | all | Filter: live, ended, or all |
page | integer | 1 | Page number |
per_page | integer | 20 | Results per page (max 100) |
Check if user is live
GET /api/v1/streams/users/{username}/live
Check whether a user is currently live streaming. Returns is_live: false (not 404) when the user exists but is not streaming.
Auth required: No
Response
{
"is_live": true,
"stream": {
"id": "a1b2c3d4-...",
"title": "Morning coding session",
"viewer_count": 89,
"status": "live"
}
}
Stream search
GET /api/v1/streams/search
Full-text search across stream titles, descriptions, and streamer usernames. Uses PostgreSQL full-text search with relevance ranking. Live streams are prioritized.
Auth required: No
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query (1–200 chars) |
category_id | UUID | No | Filter by category |
status_filter | string | No | live, ended, or all |
start_date | datetime | No | Streams started after this date |
end_date | datetime | No | Streams started before this date |
page | integer | No | Page number (default 1) |
per_page | integer | No | Results per page (max 100) |
GET /api/v1/streams/search?query=python+tutorial&status_filter=live
Search suggestions
GET /api/v1/streams/search/suggestions
Get autocomplete suggestions from stream titles, streamer usernames, and category names.
Auth required: No
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | — | Partial query (required, 1–100 chars) |
limit | integer | 5 | Max suggestions (max 20) |
Popular searches
GET /api/v1/streams/search/popular
Get popular search terms based on current live streams with high viewer counts and popular categories.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 10 | Max results (max 50) |
Trending searches
GET /api/v1/streams/search/trending
Get trending search terms based on recently started streams.
| Parameter | Type | Default | Description |
|---|---|---|---|
hours | integer | 24 | Time window in hours (max 168) |
limit | integer | 10 | Max results (max 50) |
Trending streams
GET /api/v1/streams/trending
Get trending live streams with a computed trending score (0–100). The algorithm weights viewer count (40%), viewer growth rate in the last 30 minutes (30%), stream freshness (20%), and chat engagement (10%).
| Parameter | Type | Default | Description |
|---|---|---|---|
time_window | integer | 1 | Hours to consider (1–24) |
limit | integer | 10 | Max results (max 50) |
category_id | UUID | — | Optional category filter |
Response
{
"streams": [
{
"stream": { "id": "...", "title": "...", "viewer_count": 5200, "status": "live" },
"trending_score": 87.4
}
],
"total": 10,
"limit": 10,
"time_window_hours": 1
}
Rising streamers
GET /api/v1/streams/rising
Get rising and new streamers with high viewer growth rates. Streamers are currently live, typically with fewer total streaming hours, and are growing quickly.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Max results (max 100) |
category_id | UUID | — | Optional category filter |
Streamer profiles
Get public profile
GET /api/v1/streams/streamers/{username}/profile
Get a streamer's public profile including bio, social links, follower count, partner status, and current live status.
Auth required: No
Get own profile
GET /api/v1/streams/me/profile
Get the authenticated user's own streamer profile (includes private fields).
Auth required: Yes
Update own profile
PATCH /api/v1/streams/me/profile
Update your streamer profile.
Auth required: Yes
| Field | Type | Description |
|---|---|---|
bio | string | Channel bio/description |
stream_title | string | Default stream title |
stream_category_id | UUID | Default stream category |
social_links | object | Social media links |
avatar_url | string | Avatar image URL |
banner_url | string | Channel banner URL |
Media uploads
Upload avatar
POST /api/v1/streams/me/profile/avatar
Upload an avatar image. Must be JPEG or PNG, max 2 MB. Automatically resized to 256×256 pixels.
Auth required: Yes
Content-Type: multipart/form-data
Returns {"avatar_url": "https://..."}.
Delete avatar
DELETE /api/v1/streams/me/profile/avatar
Remove the avatar image. Returns 204 No Content.
Upload banner
POST /api/v1/streams/me/profile/banner
Upload a channel banner. Must be JPEG or PNG, max 5 MB. Automatically resized to 1920×480 pixels.
Auth required: Yes
Content-Type: multipart/form-data
Returns {"banner_url": "https://..."}.
Delete banner
DELETE /api/v1/streams/me/profile/banner
Remove the channel banner. Returns 204 No Content.
Moderator management
Add moderator or VIP
POST /api/v1/streams/{stream_id}/moderators
Grant a user a moderator or VIP badge. Broadcaster only.
Auth required: Yes (broadcaster only)
{
"user_id": "...",
"badge_type": "moderator"
}
badge_type must be "moderator" or "vip".
Remove moderator or VIP
DELETE /api/v1/streams/{stream_id}/moderators/{user_id}
Remove a moderator or VIP badge. Broadcaster only. Returns 204 No Content.
List moderators
GET /api/v1/streams/{stream_id}/moderators
Get all moderators and VIPs for a stream.
| Parameter | Type | Description |
|---|---|---|
badge_type | string | Filter: moderator or vip |
Get user badges
GET /api/v1/streams/{stream_id}/users/{user_id}/badges
Get all badges a specific user holds in a stream context. Possible badges: broadcaster, moderator, vip, subscriber, verified.
Follow system
Follow a user
POST /api/v1/streams/users/{username}/follow
Follow a streamer. Notifications are enabled by default.
Auth required: Yes
{
"notifications_enabled": true
}
Returns 400 if already following or trying to follow yourself.
Unfollow a user
DELETE /api/v1/streams/users/{username}/follow
Stop following a user. Returns 204 No Content.
Auth required: Yes
Check follow status
GET /api/v1/streams/users/{username}/follow
Check whether the authenticated user is following the specified user.
Auth required: Yes
{
"following": true,
"notifications_enabled": true
}
Get followers
GET /api/v1/streams/users/{username}/followers
List users following the specified user. Paginated.
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
per_page | integer | 20 | Results per page (max 100) |
Get following
GET /api/v1/streams/users/{username}/following
List users that the specified user follows. Paginated.
Follow notifications
Get notifications
GET /api/v1/streams/notifications/follows
Get paginated follow notifications for the authenticated user. Returns most recent first.
Auth required: Yes
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
per_page | integer | 20 | Items per page (max 100) |
Get unread count
GET /api/v1/streams/notifications/follows/unread-count
Get the count of unread follow notifications. Useful for displaying notification badges.
Auth required: Yes
{ "unread_count": 3 }
Mark notification as read
POST /api/v1/streams/notifications/follows/{notification_id}/read
Mark a specific notification as read. Returns 204 No Content.
Auth required: Yes (notification owner only)
Stream schedule
Streamers can publish a recurring weekly schedule so followers know when to expect them.
Create schedule entry
POST /api/v1/streams/me/schedule
Auth required: Yes
{
"day_of_week": 1,
"start_time": "18:00",
"end_time": "20:00",
"timezone": "America/New_York",
"title": "Evening coding sessions"
}
day_of_week: 0 = Monday, 6 = Sunday.
Get own schedule
GET /api/v1/streams/me/schedule
Get your full weekly schedule grouped by day. Auth required: Yes
Get user's public schedule
GET /api/v1/streams/users/{username}/schedule
Get any user's public stream schedule. Auth required: No
Update schedule entry
PATCH /api/v1/streams/me/schedule/{schedule_id}
Auth required: Yes (owner only)
Delete schedule entry
DELETE /api/v1/streams/me/schedule/{schedule_id}
Auth required: Yes (owner only). Returns 204 No Content.
Get upcoming streams
GET /api/v1/streams/users/{username}/upcoming
Get upcoming scheduled stream instances for a user based on their recurring schedule.
| Parameter | Type | Default | Description |
|---|---|---|---|
days | integer | 7 | Days to look ahead (1–30) |
User profile (basic)
GET /api/v1/streams/users/{username}/profile
Get a user's basic profile — follower/following counts, total views, and current live status.
Auth required: No
{
"id": "...",
"username": "alice",
"display_name": "Alice Chen",
"bio": "Full-stack dev streaming daily",
"avatar_url": "https://...",
"follower_count": 1523,
"following_count": 87,
"is_live": true,
"current_stream": {
"id": "...",
"title": "Morning standup coding",
"viewer_count": 142,
"status": "live"
},
"total_views": 98432,
"created_at": "2025-01-15T09:00:00Z"
}