Skip to content

Cameras API

The cameras API is the admin-persona lookup for every /api/v1/cameras/* endpoint. Developers integrating from code use REST camera endpoints instead.

Endpoints

All paths are prefixed with /api/v1. Authentication is required on every endpoint. Role names below map to D78-D81.

MethodPathRequired rolePurpose
GET/camerasAny authenticatedList cameras visible to the caller. Viewers are scoped to their assigned sites.
POST/camerasOperator or aboveCreate a camera. Validates the connection synchronously for gateway mode.
GET/cameras/{id}Any authenticatedFetch one camera by ID.
PATCH/cameras/{id}Operator or aboveUpdate allowed fields. See Updatable fields.
DELETE/cameras/{id}Operator or aboveSoft-delete the camera (sets deleted_at).
POST/cameras/validate-connectionOperator or aboveProbe an RTSP URL before saving it.
GET/cameras/{id}/diagnosticsAny authenticatedReturn connectivity diagnostics.
GET/cameras/{id}/healthAny authenticatedLive streaming health metrics.
GET/cameras/{id}/thumbnailAny authenticatedLatest JPEG thumbnail from the camera.
POST/cameras/{id}/snapshotAny authenticatedRequest a fresh snapshot via the gateway.
POST/cameras/{id}/triggerOperator or aboveManually trigger a recording. See Trigger recording.
POST/cameras/{id}/ptzOperator or aboveSend a PTZ ContinuousMove command. Body: {direction, magnitude}. Routed through the video tunnel to the gateway. v1 supports six directions (pan_up/down/left/right + zoom_in/out). No presets.
GET/cameras/{id}/analysis-focusAny authenticated (site-scoped)Get per-camera AI analysis focus (focus text, ignore guidance, monitoring schedule, version).
PUT/cameras/{id}/analysis-focusAny authenticated (site-scoped)Update per-camera AI analysis focus. Handler at cloud/internal/devices/analysis_focus_handler.go:28 does NOT apply RequireOperator() — the route is gated only by the same auth + site-access middleware as the read endpoints. To restrict edits to operator+, the handler would need an explicit role check.
GET/cameras/{id}/analysis-focus/historyAny authenticated (site-scoped)Get analysis-focus version history (default 20, max 100 entries).
GET/analysis-focus-presetsAny authenticatedList built-in focus presets (baby_safety, package_delivery, perimeter_security, elderly_care, pet_monitoring, retail_security, traffic_monitoring).
GET/cameras/{id}/nbd-overrideOperator or aboveGet per-camera “No Big Deal” override knobs. Empty object {} if no override is set.
PATCH/cameras/{id}/nbd-overrideOperator or abovePartial-update NBD override knobs. Fields validated against the per-rule schema.
DELETE/cameras/{id}/nbd-overrideOperator or aboveClear the camera’s NBD override (camera inherits the rule’s NBD config).
GET/streams/{camera_id}/statusAny authenticatedStream status (streamable, codec, viewer count).

Updatable fields

PATCH /cameras/{id} accepts only these fields. Any other key in the request body is silently dropped.

FieldTypeDescription
namestringDisplay name.
site_iduuidMove the camera to a different site.
enabledbooleanToggle streaming and recording.
statusenumOverride status (pending, online, offline, error, disabled).
recording_duration_secinteger5 - 120.
pre_event_buffer_secinteger0 - 10.
post_event_buffer_secinteger0 - 10.
ai_analysis_modeenumsnapshot_only, multi_frame, full_video, disabled.
ai_pass_modeenumone_pass, two_pass.
prompt_pack_iduuidPer-camera prompt pack override.
ai_provider_overridestringProvider key override.
ai_model_overridestringModel ID override.
motion_sensitivityenumlow, medium, high.
detection_streamenumsub, main.
recording_streamenummain, sub.
motion_zones_jsonjsonbPolygon zones.
stream_transportstringTransport protocol override.
stream_modestringsingle or dual.

Trigger recording

POST /api/v1/cameras/{id}/trigger — manual event trigger per D49. Creates an event and records a clip using the camera’s pre- and post-event buffers.

PropertyValue
MethodPOST
Path/api/v1/cameras/{id}/trigger
Required roleOperator or above
Request bodyNone
Success status202 Accepted
Rate limit1 request per camera per 5 seconds
Rate-limit response429 Too Many Requests with Retry-After: 5
Camera must bestatus = online (otherwise 409 Conflict)
Behaviour when a recording is already activeGateway-mode: extends the active recording instead of creating a new event; returns status: "recording_extended". Direct-mode: extend is not supported — every trigger creates a fresh event (B-12, closed 2026-05-28).
Audit actioncamera.manual_trigger (always for direct-mode; gateway-mode when no active recording) or camera.recording_extended (gateway-mode only when extending)

Response body:

{
"request_id": "<hex-32>",
"event_id": "<uuid>",
"camera_id": "<uuid>",
"triggered_at": "2026-04-22T09:15:00Z",
"status": "triggered",
"message": "Recording triggered successfully",
"transport": "tunnel"
}
FieldTypeDescription
request_idstring32-char hex; deduplication key.
event_iduuidNew event ID (or the existing ID when extending).
camera_iduuidEcho of the path parameter.
triggered_attimestampServer-side trigger time in UTC.
statusenumtriggered or recording_extended.
messagestringHuman-readable status.
transportenumtunnel for gateway mode, direct for direct mode, fallback for the gateway upload path.

List cameras query parameters

Supported query parameters on GET /cameras.

ParameterTypeDescription
site_iduuidFilter by site.
statusstringFilter by status enum value.
typestringFilter by camera type (onvif, rtsp).
connection_modestringFilter by connection mode (direct, gateway).
gateway_iduuidFilter by gateway.
cursorstringPagination cursor.
limitintegerPage size. Default 20, max 100.

Stream status response

GET /streams/{camera_id}/status:

FieldTypeDescription
streamablebooleanTrue when enabled and status == "online".
webrtc_supportedbooleanTrue for h264 and h265 codecs.
codecstringCurrent codec or empty string.
resolutionstringWIDTHxHEIGHT or empty.
connection_modestringdirect or gateway.
go2rtc_statusstringactive or inactive.
active_viewersintegerCurrent WebRTC viewer count.