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 when source_mode is "file".
  • stream_type (string, default "radio") — radio or tv.
  • source_mode (string, default "stream") — stream for a continuous live source, or file for a finite audio file (downloaded, segmented, runs once to completion, then stops).
  • language (string, default "pl") — transcription language.
  • chunk_duration_seconds (int, default 180) — transcription chunk length.
  • callback_url (string, optional) — webhook target; each new digest is POSTed here.
  • final_digest_only (bool, default false) — when true, deliver and keep only the single final consolidated digest instead of periodic ones. Ideal for files and finished broadcasts.
  • include_transcript (bool, default false) — when true, each delivered digest payload gains a transcript_url (durable public link to the raw .txt on Cloudflare R2, or null if no transcript was produced) and a transcript_window_seconds ([start, end] audio range the transcript covers). Each periodic digest carries its own window's transcript; combined with final_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), plus watch_streams / watch_videos (both default true) and poll_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.