Surveillance
Pi’s surveillance API gives you three surfaces: an async job endpoint for per-frame analysis, a policy management endpoint for reusable behavior rules, and a Server-Sent Events stream for real-time incident delivery.Keep SSE connections alive and implement automatic reconnection. Pi emits
: heartbeat comments every 15 seconds. If your client drops the connection, reconnect with the same query parameters.Submit a stream job
POST /api/v1/surveillance/streams
Runs perception on a single frame (when input.data is provided), evaluates inline behaviors and stored policies, optionally narrates incidents with Gemini, and persists incidents for SSE subscribers.
Request
Body parameters
Optional identifier for the camera or stream. Max 256 characters. Used to scope policies and SSE event filtering.
Stream source metadata.
Built-in behavior preset. One of
"retail_security", "warehouse_safety", "smart_city", "residential_perimeter", "construction_site", "parking_lot", "school_campus", "healthcare_facility". Your explicit behaviors override the preset when non-empty.Object class labels to watch for, e.g.
["person", "car", "backpack"]. Max 64 items.Inline behavior rules. Supported types:
"loitering", "intrusion", "crowd_growth", "object_left", "perimeter_breach", "speed_violation", "wrong_direction". Max 50 rules.Each rule requires type and zone. Additional fields per type:loitering:seconds(1–86400)intrusion: optionalclassesarraycrowd_growth:countandwindow_secobject_left:seconds(1–86400)perimeter_breach: optionalboundary("inside"or"outside")speed_violation:max_speed_mpswrong_direction:allowed_heading_degand optionaltolerance_deg
Anomaly detection config. Set
enabled: true and sensitivity (0–1, default 0.7).Delivery and format config.
Alert filtering config.
Arbitrary context including
zones (a map of zone id to { xyxy: [x1, y1, x2, y2] } in normalized coordinates). Must serialize to at most 16,000 characters.Single-frame perception sample.
Zero-based index of this frame in the stream. Defaults to
0.Response
Returns202 Accepted.
GET /api/v1/jobs/:id?wait_for_completion=true for data.payload.output containing stream_id, perception results, and incidents.
Create or update a policy
POST /api/v1/surveillance/policies
Persist a reusable behavior detection policy scoped to a specific stream or global (when stream_id is empty). Stored policies are automatically evaluated against every stream job for the matching stream_id.
Request
Body parameters
Target stream. Set to
null or omit for a global policy that applies to all streams.Human-readable policy name. Max 200 characters.
Behavior type. One of
"loitering", "intrusion", "crowd_growth", "object_left", "perimeter_breach", "speed_violation", "wrong_direction", "custom".Detection thresholds:
zone, duration_seconds, count_threshold, window_sec, speed_threshold_mps, direction_deg, boundary.Action on trigger:
severity ("info", "warning", "critical"), message_template, cooldown_seconds.Whether the policy is active. Defaults to
true.Subscribe to real-time events (SSE)
GET /api/v1/surveillance/events
Opens a persistent text/event-stream connection. Pi emits incident events as JSON and : heartbeat comments every 15 seconds to keep the connection alive.
Query parameters
Filter events to a specific stream. When set, you also receive global policies (those with no
stream_id).Minimum severity filter. One of
"info", "warning", "critical".Consuming SSE events
SSE event shape
Eachincident event body is a JSON object:
Error codes
| Code | HTTP | Description |
|---|---|---|
surveillance_disabled | 403 | SURVEILLANCE_ENABLED=false in server environment |
invalid_request_body | 400 | Schema validation failed |
job_create_failed | 500 | Database insert failed |
job_trigger_failed | 502 | Background worker not reachable |