API Reference
Base URL: https://api.stream2llm.com
Authentication
Stream endpoints (/v2/streams/*) use the X-API-Key header with a key from your dashboard. Account endpoints (/me, /me/keys) use a Bearer JWT from Kinde — these are intended for the dashboard, not for API clients.
POST /v2/streams/subscriptions
Subscribe to a live stream. The runner starts monitoring within seconds.
Body
name(string, required) — a label for the subscription.stream_url(string, required) — the audio/TV stream URL, or a direct audio file URL whensource_modeis"file".stream_type(string, default"radio") —radioortv.source_mode(string, default"stream") —streamfor a continuous live source, orfilefor a finite audio file (downloaded, segmented, runs once to completion, then stops).language(string, default"pl") — transcription language.chunk_duration_seconds(int, default180) — transcription chunk length.callback_url(string, optional) — webhook target; each new digest is POSTed here.final_digest_only(bool, defaultfalse) — when true, deliver and keep only the single final consolidated digest instead of periodic ones. Ideal for files and finished broadcasts.include_transcript(bool, defaultfalse) — when true, each delivered digest payload gains atranscript_url(durable public link to the raw.txton Cloudflare R2, ornullif no transcript was produced) and atranscript_window_seconds([start, end]audio range the transcript covers). Each periodic digest carries its own window's transcript; combined withfinal_digest_only, the single final digest carries the whole run's transcript. Note: transcripts are assembled from retained chunks — a continuous run longer than the 48h hot-retention window may yield a partial transcript.schedule(object, optional) — restrict monitoring to time windows:{"timezone":"Europe/Warsaw","windows":[{"start":"06:00","end":"09:00"}]}. No windows → runs 24/7.
Response (201)
{"id":"abc-123","name":"TOK FM","stream_url":"...","stream_type":"radio","source_mode":"stream","language":"pl","status":"active","chunk_duration_seconds":180,"callback_url":null,"final_digest_only":false,"include_transcript":false,"created_at":"..."}GET /v2/streams/subscriptions
List the subscriptions owned by the calling API key.
GET /v2/streams/subscriptions/{id}
Fetch a single subscription.
POST /v2/streams/subscriptions/{id}/stop
Stop monitoring. The runner cancels the stream on its next reconcile.
POST /v2/streams/subscriptions/{id}/start
Resume a stopped subscription.
DELETE /v2/streams/subscriptions/{id}
Soft-delete a subscription (stops monitoring; history is retained).
GET /v2/streams/subscriptions/{id}/digests
Consolidated news digests for the subscription, oldest first. Each digest covers a time window and groups stories under payload. Optional limit query (1–100, default 20). With final_digest_only there is just one digest, written at the end. When include_transcript is enabled on the subscription, each digest also includes transcript_url (a durable public link to the raw transcript .txt on Cloudflare R2, or null) and transcript_window_seconds ( [start, end] seconds of the audio range covered). Each periodic digest carries its own window slice; combined with final_digest_only, the single final digest carries the whole run's transcript.
[{"digest_id":"...","window_start":0,"window_end":900,"chunk_count":5,
"callback_status":null,"processed_at":"...",
"transcript_url":"https://storage.stream2llm.com/transcripts/abc-123/0-900.txt",
"transcript_window_seconds":[0,900],
"payload":{"stories":[
{"title":"...","is_news":true,"summary":"...",
"facts":[{"text":"..."}],"quotes":[{"text":"...","speaker":"..."}]}]}}]GET /v2/streams/subscriptions/{id}/results
Raw transcribed chunks (with per-chunk topics), most recent first.
GET /v2/streams/subscriptions/{id}/results/stream
Server-Sent Events. New chunks and digests are pushed live. Authenticate with the X-API-Key header (works with curl / httpx / EventSource polyfills that support headers).
GET /v2/streams/subscriptions/{id}/entities
The rolling entity memory — people, organizations, and topics consolidated across windows. Sort with sort=last_seen (default) or first_seen; paginate with limit / offset.
YouTube
YouTube endpoints live under /v2/youtube and share the same X-API-Key auth. A monitor watches a channel and auto-spawns a stream subscription for each new live broadcast and video; an item processes a single video or VOD. Both accept the same language, chunk_duration_seconds, callback_url, schedule, final_digest_only, and include_transcript options as stream subscriptions, and the resulting digests are read back through the stream subscription endpoints above.
POST /v2/youtube/monitors— start monitoring a channel. Body:channel_url(required), pluswatch_streams/watch_videos(both default true) andpoll_interval_seconds(default 300).GET /v2/youtube/monitors— list your monitors.GET /v2/youtube/monitors/{id}— fetch one monitor.GET /v2/youtube/monitors/{id}/subscriptions— the subscriptions this monitor has spawned.POST /v2/youtube/monitors/{id}/stop·/start— pause / resume a monitor.DELETE /v2/youtube/monitors/{id}— delete the monitor and purge its child subscriptions.POST /v2/youtube/items— process a single video / VOD. Body:url(required) +name. Returns a stream subscription.
GET /me
(Bearer JWT) Current user + list of active (non-revoked) API keys.
POST /me/keys
(Bearer JWT) Create a new API key. The raw key is shown once.
# Request
{"label":"Production"}
# Response (201) — raw key shown ONCE
{"id":"...","label":"Production","key_prefix":"str_a1b2c3d4","key":"str_...","created_at":"..."}DELETE /me/keys/{id}
(Bearer JWT) Soft-delete a key. Subsequent requests with that key return 401.
Errors
401— missing/invalid/revoked key, or bad JWT.403— account pending approval (key creation blocked).404— unknown subscription, or one owned by another key.422— malformed request body.