Three endpoints,
one continuous loop.
Every sample below is rendered from src/lib/contracts/* and the route handlers under src/app/api/v1/*. The same literal JSON is what your code parses — if a field changes, this page updates in the same change.
better-auth.session_token cookie. Read the auth guide.Three streams endpoints, pulled from /openapi/streams.yaml.
Methods, intents, and request/response samples rendered directly from /openapi/streams.yaml. The curl and the JSON byte-for-byte match what the route handlers emit — for constraints, every field, and error envelopes, jump to /docs/api/streams.
/api/v1/streamsRegister a stream
Upsert a stream by its sourceUrl. The handler validates the body with zod, runs the SSRF guard against sourceUrl, then upserts by sourceUrl — POST is idempotent, so re-posting the same URL returns the existing record instead of 409.
A fresh row is initialized with agentState: 'healthy', status: 'watching', and uptimePct: 100 as a placeholder until the first probe lands. Returns 201 with the full row.
curl -X POST https://streamwake.polsia.io/api/v1/streams \
-H "content-type: application/json" \
-b "better-auth.session_token=<your-session-cookie>" \
-d '{
"sourceUrl": "https://example.com/manifest.m3u8"
}'{
"id": "ckq3xstreamabc123",
"sourceUrl": "https://example.com/manifest.m3u8",
"name": "Primary CDN — eu-west",
"targetRegion": "eu-west",
"createdAt": "2026-08-03T18:24:11.000Z",
"agentState": "healthy",
"status": "watching",
"lastAction": "registered",
"lastCheckedAt": null,
"uptimePct": 100
}/api/v1/streamsList monitored streams
Returns the 50 most recently created streams, ordered by createdAt descending. Each row carries the same shape as the POST response (StreamItem), with uptimePct computed from the last 24 hours of StreamProbe rows. Rows with no probes in the window render as 100%.
curl https://streamwake.polsia.io/api/v1/streams \
-b "better-auth.session_token=<your-session-cookie>"{
"items": [
{
"id": "ckq3xstreamabc123",
"sourceUrl": "https://example.com/manifest.m3u8",
"name": "Primary CDN — eu-west",
"targetRegion": "eu-west",
"createdAt": "2026-08-03T18:24:11.000Z",
"agentState": "healthy",
"status": "watching",
"lastAction": "registered",
"lastCheckedAt": "2026-08-03T18:25:00.000Z",
"uptimePct": 100
},
{
"id": "ckq3xstreamdef456",
"sourceUrl": "https://backup.example.com/manifest.m3u8",
"name": "Backup CDN — eu-west",
"targetRegion": "eu-west",
"createdAt": "2026-08-02T11:02:08.000Z",
"agentState": "degraded",
"status": "degraded",
"lastAction": "raised the latency budget and re-probed to confirm the trend",
"lastCheckedAt": "2026-08-03T18:25:00.000Z",
"uptimePct": 96
}
]
}/api/v1/streams/:idRead a single stream's status
Returns the live StreamStatus for one stream. The uptimePct is computed from the same 24-hour probe window as the list endpoint, so the numbers always agree. Returns 404 if the id is unknown.
curl https://streamwake.polsia.io/api/v1/streams/ckq3xstreamabc123 \
-b "better-auth.session_token=<your-session-cookie>"{
"id": "ckq3xstreamabc123",
"sourceUrl": "https://example.com/manifest.m3u8",
"agentState": "healthy",
"uptimePct": 100,
"lastAction": "registered",
"lastCheckedAt": "2026-08-03T18:25:00.000Z"
}Want every field pulled straight from the spec?
The dedicated streams reference renders every endpoint, parameter table, request body, response schema, and error envelope directly from /openapi/streams.yaml. Edit the spec and the page re-renders in the same change.
/api/v1/agentsRecent agent activity
Returns the most recent 100 StreamProbe rows joined with their stream. Three transformations happen on the way out:
- severity —
healthy → info,degraded → warn,failing → critical. - anomalyClass —
no anomalyfor healthy;slow responseorclient errorfor degraded;network / timeoutor5xx server errorfor failing. - fix / action — when a probe is failing AND the stream has no subsequent healthy probe, both fields flip to
investigating; otherwisefixechoesStream.lastActionandactionfalls through one of fouractionForbranches by status and latency.
curl https://streamwake.polsia.io/api/v1/agents \
-b "better-auth.session_token=<your-session-cookie>"{
"items": [
{
"id": "ckq3xprobe123",
"streamId": "ckq3xstreamabc123",
"sourceUrl": "https://example.com/manifest.m3u8",
"streamName": "Primary CDN — eu-west",
"severity": "info",
"anomalyClass": "no anomaly",
"fix": "registered",
"action": "no action needed — stream healthy",
"createdAt": "2026-08-03T18:25:00.000Z",
"latencyMs": 142
},
{
"id": "ckq3xprobe124",
"streamId": "ckq3xstreamdef456",
"sourceUrl": "https://backup.example.com/manifest.m3u8",
"streamName": "Backup CDN — eu-west",
"severity": "warn",
"anomalyClass": "slow response",
"fix": "raised the latency budget and re-probed to confirm the trend",
"action": "raised the latency budget and re-probed to confirm the trend",
"createdAt": "2026-08-03T18:25:00.000Z",
"latencyMs": 1840
}
]
}Every body, verbatim.
Consolidated across all four endpoints — grep this table when an error code comes back and you want the exact bytes the handler emitted.
| Status | Body | When |
|---|---|---|
400 | | Zod validation failed on the request body, or the SSRF guard refused sourceUrl (loopback / RFC 1918 / link-local). |
401 | | No session cookie, or the cookie is expired. Re-auth via /api/auth/sign-in/email and retry. |
500 | | Unexpected server error — safe to retry. |
404 | | Returned by GET /api/v1/streams/<id> when the id is unknown. |
400 | | Zod validation failed on the request body, or the SSRF guard refused sourceUrl (loopback / RFC 1918 / link-local). |
From zero,
to a watched stream.
The quickstart walks every endpoint above in order — register a stream, read it back, then open /app/streams and watch the first probe land.
Also see the player SDK reference for the npm/CDN install and the TelemetryEvent wire format → /docs/sdk/web.