Event endpoints
Event endpoints
All endpoints live under /api/v1/events. Events are scoped by the JWT’s org_id; viewers are additionally filtered by site-access (D78). There is no dedicated “acknowledge” or “dismiss” verb — acknowledge is a PATCH setting acknowledged: true; “dismiss” does not exist in the current API and is modelled as DELETE /api/v1/events/{id} (admin-only, soft).
GET /api/v1/events
List events, optionally filtered.
Since: v1.0 Required role: viewer (site-scoped)
Query parameters
| Name | Type | Default | Constraints |
|---|---|---|---|
camera_id | uuid | — | Filters to one camera |
site_id | uuid | — | Filters to one site |
date_from | string | — | RFC3339 or YYYY-MM-DD |
date_to | string | — | RFC3339 or YYYY-MM-DD |
trigger_type | enum | — | motion, ai_tag, manual |
ai_status | enum | — | pending, completed, skipped, failed |
starred | bool | — | Only starred events when true |
cursor | string | null | Pagination cursor |
limit | int | 20 | 1-100 |
Response 200
{ "data": [ { "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f", "camera_id": "550e8400-e29b-41d4-a716-446655440000", "camera_name": "Loading Dock East", "camera_deleted": false, "trigger_type": "ai_tag", "triggered_at": "2026-04-21T13:45:22Z", "summary": "Person carrying package approaches dock door", "tags": ["person", "package"], "ai_status": "completed", "acknowledged": false, "starred": false, "snapshot_url": "https://storage.googleapis.com/bkt-cloud-ai/..." } ], "next_cursor": null, "total": 1}Error responses
| Code | Body.error | Meaning |
|---|---|---|
| 401 | auth_required | Missing or invalid token |
| 403 | forbidden | Viewer outside site scope |
| 429 | rate_limited | See /developer/rate-limits |
Examples
curl -H "Authorization: Bearer sk_live_abc123" \ "https://novavms.novalien.com/api/v1/events?trigger_type=ai_tag&date_from=2026-04-20"const events = await novavms.events.list({ triggerType: 'ai_tag', dateFrom: '2026-04-20',});events = client.events.list(trigger_type="ai_tag", date_from="2026-04-20")GET /api/v1/events/{id}
Return a single event with full detail (narrative, clip/snapshot URLs, prev/next navigation).
Since: v1.0 Required role: viewer (site-scoped)
Response 200
{ "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f", "camera_id": "550e8400-e29b-41d4-a716-446655440000", "camera_name": "Loading Dock East", "camera_deleted": false, "trigger_type": "ai_tag", "triggered_at": "2026-04-21T13:45:22Z", "clip_start_at": "2026-04-21T13:45:12Z", "clip_end_at": "2026-04-21T13:45:42Z", "duration_sec": 30, "summary": "Person carrying package approaches dock door", "narrative": "A courier in an orange vest walked to the dock...", "tags": ["person", "package", "vest"], "ai_status": "completed", "acknowledged": false, "acknowledged_by": null, "acknowledged_at": null, "starred": false, "notes": null, "clip_codec": "h264", "snapshot_url": "https://storage.googleapis.com/bkt-cloud-ai/...", "clip_url": "https://storage.googleapis.com/bkt-cloud-ai/...", "recording_source": "gateway_ring_buffer", "prev_event_id": null, "next_event_id": null}Error responses
| Code | Body.error | Meaning |
|---|---|---|
| 401 | auth_required | Missing or invalid token |
| 403 | forbidden | Viewer outside site scope |
| 404 | not_found | Event not in caller’s org |
Examples
curl -H "Authorization: Bearer sk_live_abc123" \ https://novavms.novalien.com/api/v1/events/c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5fconst ev = await novavms.events.get('c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f');ev = client.events.get("c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f")PATCH /api/v1/events/{id}
Acknowledge, star, or annotate the event. Setting acknowledged: true records the caller’s ID and the current timestamp server-side.
Since: v1.0 Required role: operator
Request body
| Name | Type | Default | Constraints |
|---|---|---|---|
acknowledged | bool | — | true to acknowledge; false to clear |
starred | bool | — | — |
notes | string | — | Up to 2000 chars |
Response 200
Returns the updated event — same shape as GET /api/v1/events/{id}.
Error responses
| Code | Body.error | Meaning |
|---|---|---|
| 400 | validation_error | Empty body or unknown field |
| 403 | forbidden | Role insufficient |
| 404 | not_found | Event not in caller’s org |
Examples
curl -X PATCH https://novavms.novalien.com/api/v1/events/c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f \ -H "Authorization: Bearer sk_live_abc123" \ -H "Content-Type: application/json" \ -d '{"acknowledged":true,"notes":"Confirmed courier, no action needed"}'await novavms.events.update('c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f', { acknowledged: true, notes: 'Confirmed courier, no action needed',});client.events.update( "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f", acknowledged=True, notes="Confirmed courier, no action needed",)DELETE /api/v1/events/{id}
Soft-delete the event. This is the closest analogue to “dismiss”; see the note at the top of this page.
Since: v1.0 Required role: admin
Response 204
Empty body.
Error responses
| Code | Body.error | Meaning |
|---|---|---|
| 403 | forbidden | Role insufficient |
| 404 | not_found | Event not in caller’s org |
Examples
curl -X DELETE https://novavms.novalien.com/api/v1/events/c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f \ -H "Authorization: Bearer sk_live_abc123"await novavms.events.delete('c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f');client.events.delete("c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f")GET /api/v1/events/export
Stream a CSV export of events matching the same filter set as GET /api/v1/events. Response is text/csv; charset=utf-8 with Content-Disposition: attachment.
Since: v1.1 Required role: operator
Query parameters
Same as GET /api/v1/events. Server caps results at EVENT_EXPORT_MAX_ROWS (default 10000).
Response 200
id,camera_id,camera_name,trigger_type,triggered_at,duration_sec,summary,tags,ai_status,acknowledged,starredc1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f,550e8400-e29b-41d4-a716-446655440000,Loading Dock East,ai_tag,2026-04-21T13:45:22Z,30,Person carrying package approaches dock door,"person,package",completed,false,falseError responses
| Code | Body.error | Meaning |
|---|---|---|
| 403 | forbidden | Role insufficient |
| 413 | payload_too_large | Filter matches more rows than the export cap |
Examples
curl -H "Authorization: Bearer sk_live_abc123" \ "https://novavms.novalien.com/api/v1/events/export?date_from=2026-04-01&date_to=2026-04-21" \ --output events-april.csvconst csv = await novavms.events.export({ dateFrom: '2026-04-01', dateTo: '2026-04-21',});csv_bytes = client.events.export(date_from="2026-04-01", date_to="2026-04-21")