API Reference#
The backend is a FastAPI application that serves REST APIs under the /api prefix for stream lifecycle management, alert retrieval, frame-registry inspection, and runtime UI configuration.
Interactive API docs#
When the stack is running, FastAPI provides OpenAPI/Swagger UI at:
http://localhost:9100/docs
If the backend is exposed on a different host or port, adjust accordingly.
REST Endpoints#
Health Check#
GET /api/health- Liveness and basic runtime status
Health Response Schema#
{
"status": "healthy",
"streams_active": 0,
"uptime_seconds": 12.4,
"timestamp": "2026-09-07T10:20:30.123456+00:00"
}
Runtime Config#
GET /api/runtime-config.js- Browser runtime configuration as JavaScript (window.RUNTIME_CONFIG = {...};)
This endpoint is consumed by the UI to resolve WebRTC signaling and metrics service URLs.
Streams#
GET /api/streams- List all active streams and live processing statePOST /api/streams- Create/start a new stream pipelineDELETE /api/streams/{stream_id}- Stop and remove a stream pipeline
Create Stream Request Schema (POST /api/streams)#
{
"stream_id": "camera-lobby",
"url": "rtsp://example.com/stream",
"alert_prompt": "Look for visible fire and describe its location.",
"deep_analyzer_prompt": "Review the clip for evidence of fire and summarize what happens."
}
Notes:
urlis required.alert_promptanddeep_analyzer_promptare required.stream_iddefaults todefaultif omitted/empty.urlmust usertsp://orrtsps://. HTTP and HTTPS URLs are not supported.stream_id, when provided, must contain 1-64 letters, digits, underscores, or hyphens.Each prompt is limited to 4096 characters.
Create Stream Response Schema#
{
"status": "added",
"stream_id": "camera-lobby"
}
List Streams Response Schema (GET /api/streams)#
{
"streams": [
{
"stream_id": "camera-lobby",
"url": "rtsp://example.com/stream",
"alert_prompt": "Look for visible fire and describe its location.",
"deep_analyzer_prompt": "Review the clip for evidence of fire and summarize what happens.",
"publishing": true,
"codec": "h264",
"resolution": "576x320",
"reconnect_count": 0,
"whep_path": "/camera-lobby/whep",
"caption": "Yes",
"caption_ts": 1757240432.117,
"ttft_ms": 73.2,
"tpot_ms": 18.7,
"throughput_tps": 54.1,
"alert_count": 3
}
]
}
Delete Stream Response Schema (DELETE /api/streams/{stream_id})#
{
"status": "removed",
"stream_id": "camera-lobby"
}
Alerts#
GET /api/streams/{stream_id}/alerts- Paginated alert listing (limit,offsetquery params)GET /api/streams/{stream_id}/alerts/{frame_id}- Alert detail recordGET /api/streams/{stream_id}/alerts/{frame_id}/thumbnail- Alert thumbnail image (image/jpeg)GET /api/streams/{stream_id}/alerts/{frame_id}/video- Alert video clip (video/mp4)
List Alerts Response Schema (GET /api/streams/{stream_id}/alerts)#
{
"total": 2,
"alerts": [
{
"frame_id": "9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7",
"trigger_caption": "Yes",
"confirmed": true,
"thumbnail_url": "/api/streams/camera-lobby/alerts/9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7/thumbnail",
"uploaded_at": "2026-09-07T10:17:40.100000+00:00"
}
]
}
Alert Detail Response Schema (GET /api/streams/{stream_id}/alerts/{frame_id})#
{
"stream_id": "camera-lobby",
"frame_id": "9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7",
"trigger_caption": "Yes",
"confirmed": true,
"thumbnail_url": "/api/streams/camera-lobby/alerts/9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7/thumbnail",
"description": "Short multi-frame analysis summary.",
"metrics": {
"ttft_ms": 70.2,
"throughput_tps": 50.4
},
"model": "Qwen3-VL-8B-Instruct",
"device": "GPU",
"uploaded_at": "2026-09-07T10:17:40.100000+00:00",
"video_url": "/api/streams/camera-lobby/alerts/9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7/video"
}
Alerts Query Parameters#
limit(default20, min1, max100)offset(default0, min0)
Frame Registry#
GET /api/registry/stats- Registry totals and per-stream countsGET /api/registry/stream/{stream_id}- Latest frame records for one stream (limitquery param)GET /api/registry/frame/{frame_id}- Lookup a specific frame record by UUID
Registry Stats Response Schema (GET /api/registry/stats)#
{
"total": 134,
"per_stream_capacity": 500,
"per_stream": {
"camera-lobby": 84,
"camera-parking": 50
}
}
Registry Records Response Schema#
Returned by GET /api/registry/stream/{stream_id} (limit defaults to 50).
{
"records": [
{
"frame_id": "9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7",
"stream_id": "camera-lobby",
"segment_path": "segments/camera-lobby_segment_0012.mp4",
"pts_seconds": 173.2,
"created_ts": 1757240432.117
}
]
}
Registry Frame Detail Response Schema (GET /api/registry/frame/{frame_id})#
{
"frame_id": "9dd96a2f-17b9-41a0-a1c5-e3f8f76b07a7",
"stream_id": "camera-lobby",
"rtsp_url": "rtsp://example.com/stream",
"segment_path": "segments/camera-lobby_segment_0012.mp4",
"pts_seconds": 173.2,
"created_ts": 1757240432.117
}
Streaming Endpoints#
The stack also includes two related streaming surfaces outside of FastAPI:
WebRTC playback signaling and media via MediaMTX WHEP (
/{stream_id}/whep)System metrics via the bundled
metrics-manager(intel/metrics-manager) SSE endpoint (/metrics/stream)
WebRTC Playback (MediaMTX WHEP)#
POST /{stream_id}/whep
This endpoint is served by MediaMTX, not FastAPI. The backend returns whep_path from GET /api/streams, and the UI completes SDP offer/answer negotiation against this WHEP path.
System Metrics SSE (metrics-manager)#
GET /metrics/stream
This endpoint is served by the metrics-manager sidecar service (default port 9090), not by the FastAPI backend. The UI subscribes with EventSource for live CPU/GPU/NPU/memory/power telemetry.
Example URL:
http://localhost:9090/metrics/stream
Related metrics capability endpoint:
GET /api/v1/capabilities?profile=minimal
Error Behavior#
Typical API error codes:
400- invalid request payload or malformed path/query values422- request body violates schema limits (for example, a prompt exceeds 4096 characters)404- stream, alert, thumbnail, video, or frame record not found409- stream conflict (for example, duplicatestream_id)