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 state

  • POST /api/streams - Create/start a new stream pipeline

  • DELETE /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:

  • url is required.

  • alert_prompt and deep_analyzer_prompt are required.

  • stream_id defaults to default if omitted/empty.

  • url must use rtsp:// or rtsps://. 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, offset query params)

  • GET /api/streams/{stream_id}/alerts/{frame_id} - Alert detail record

  • GET /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 (default 20, min 1, max 100)

  • offset (default 0, min 0)

Frame Registry#

  • GET /api/registry/stats - Registry totals and per-stream counts

  • GET /api/registry/stream/{stream_id} - Latest frame records for one stream (limit query 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 values

  • 422 - request body violates schema limits (for example, a prompt exceeds 4096 characters)

  • 404 - stream, alert, thumbnail, video, or frame record not found

  • 409 - stream conflict (for example, duplicate stream_id)