Events API¶
The Events API provides endpoints for managing security events in the NEM home security monitoring system. Events are aggregated collections of detections that represent security-relevant activities.
Source: backend/api/routes/events.py
Overview¶
Events are created when the AI pipeline detects security-relevant activity. Each event:
- Contains one or more detections
- Has an LLM-generated risk score (0-100)
- Includes a summary and reasoning from Nemotron
- Supports soft-delete for recovery
Endpoints¶
List Events¶
List security events with optional filtering and pagination.
Source: backend/api/routes/events.py:224-468
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
camera_id | string | null | Filter by camera ID |
risk_level | string | null | Filter by risk level (low, medium, high, critical) |
start_date | datetime | null | Filter events after this date (ISO 8601) |
end_date | datetime | null | Filter events before this date (ISO 8601) |
reviewed | boolean | null | Filter by review status |
object_type | string | null | Filter by detected object type |
limit | integer | 50 | Maximum results (1-100) |
offset | integer | 0 | Results to skip (deprecated, use cursor) |
cursor | string | null | Pagination cursor from previous response |
fields | string | null | Comma-separated fields for sparse fieldsets |
include_deleted | boolean | false | Include soft-deleted events |
Response¶
{
"items": [
{
"id": 1,
"camera_id": "front_door",
"started_at": "2026-01-23T12:00:00Z",
"ended_at": "2026-01-23T12:02:30Z",
"risk_score": 75,
"risk_level": "medium",
"summary": "Person detected near front entrance",
"reasoning": "Person approaching entrance during daytime, no suspicious behavior",
"llm_prompt": "<|im_start|>system\nYou are a home security risk analyzer...",
"reviewed": false,
"notes": null,
"snooze_until": null,
"detection_count": 5,
"detection_ids": [1, 2, 3, 4, 5],
"thumbnail_url": "/api/detections/1/image",
"enrichment_status": {
"status": "full",
"successful_models": ["violence", "weather", "face", "clothing"],
"failed_models": [],
"errors": {},
"success_rate": 1.0
},
"deleted_at": null
}
],
"pagination": {
"total": 150,
"limit": 50,
"offset": 0,
"next_cursor": "eyJpZCI6IDUwLCAiY3JlYXRlZF9hdCI6ICIyMDI2LTAxLTIzVDEyOjAwOjAwWiJ9", // pragma: allowlist secret
"has_more": true
},
"deprecation_warning": null
}
Source: backend/api/schemas/events.py:147-193
HTTP Status Codes¶
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Invalid date range or cursor |
| 422 | Validation error |
Get Event Statistics¶
Get aggregated event statistics including risk distribution and per-camera counts.
Source: backend/api/routes/events.py:471-603
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
camera_id | string | null | Filter statistics by camera |
start_date | datetime | null | Start of date range |
end_date | datetime | null | End of date range |
Response¶
{
"total_events": 44,
"events_by_risk_level": {
"critical": 2,
"high": 5,
"medium": 12,
"low": 25
},
"risk_distribution": [
{ "risk_level": "critical", "count": 2 },
{ "risk_level": "high", "count": 5 },
{ "risk_level": "medium", "count": 12 },
{ "risk_level": "low", "count": 25 }
],
"events_by_camera": [
{
"camera_id": "front_door",
"camera_name": "Front Door",
"event_count": 30
},
{
"camera_id": "back_door",
"camera_name": "Back Door",
"event_count": 14
}
]
}
Source: backend/api/schemas/events.py:243-284
Get Timeline Summary¶
Get bucketed event data for timeline visualization. Supports different zoom levels with varying bucket sizes.
Source: backend/api/routes/events.py:621-779
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
start_date | datetime | required | Start of timeline range |
end_date | datetime | required | End of timeline range |
camera_id | string | null | Filter by camera |
bucket_size | string | "hour" | Bucket size (hour, day, week) |
Response¶
{
"buckets": [
{
"timestamp": "2026-01-15T06:00:00Z",
"event_count": 5,
"max_risk_score": 45
},
{
"timestamp": "2026-01-15T07:00:00Z",
"event_count": 12,
"max_risk_score": 85
}
],
"total_events": 17,
"start_date": "2026-01-15T06:00:00Z",
"end_date": "2026-01-15T08:00:00Z"
}
Source: backend/api/schemas/events.py:287-349
Search Events¶
Full-text search across events using PostgreSQL text search.
Source: backend/api/routes/events.py:782-892
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | required | Search query (min 1 character) |
camera_id | string | null | Filter by camera |
min_risk_score | integer | null | Minimum risk score (0-100) |
start_date | datetime | null | Filter after date |
end_date | datetime | null | Filter before date |
limit | integer | 50 | Maximum results (1-1000) |
offset | integer | 0 | Results to skip |
Response¶
Results include a relevance_score field indicating search match quality.
Export Events¶
Export events as CSV or Excel file.
Source: backend/api/routes/events.py:895-999
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
format | string | "csv" | Export format (csv, xlsx) |
camera_id | string | null | Filter by camera |
start_date | datetime | null | Filter after date |
end_date | datetime | null | Filter before date |
risk_level | string | null | Filter by risk level |
Response¶
Returns file download with appropriate Content-Type header.
Rate Limiting: Export tier (5 requests/minute)
Get Single Event¶
Get detailed information about a specific event.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
event_id | integer | Event ID |
Response¶
Returns full EventResponse object.
HTTP Status Codes¶
| Code | Description |
|---|---|
| 200 | Success |
| 404 | Event not found |
Update Event¶
Update event metadata (reviewed status, notes, snooze).
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
event_id | integer | Event ID |
Request Body¶
Source: backend/api/schemas/events.py:127-144
HTTP Status Codes¶
| Code | Description |
|---|---|
| 200 | Success |
| 404 | Event not found |
| 422 | Validation error |
Delete Event¶
Soft-delete an event. The event can be restored later.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
event_id | integer | Event ID |
HTTP Status Codes¶
| Code | Description |
|---|---|
| 204 | Success (no content) |
| 404 | Event not found |
Restore Event¶
Restore a soft-deleted event.
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
event_id | integer | Event ID |
HTTP Status Codes¶
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Event is not deleted |
| 404 | Event not found |
List Deleted Events¶
List soft-deleted events for the "trash" view.
Source: backend/api/schemas/events.py:352-393
Response¶
Returns DeletedEventsListResponse with same structure as list events.
Bulk Operations¶
Bulk Create Events¶
Create multiple events in a single request.
Rate Limiting: Bulk tier (10 requests/minute)
Request Body¶
{
"events": [
{
"camera_id": "front_door",
"started_at": "2026-01-23T12:00:00Z",
"risk_score": 45
}
]
}
Response¶
Returns HTTP 207 Multi-Status with per-item results.
Bulk Update Events¶
Update multiple events in a single request.
Rate Limiting: Bulk tier (10 requests/minute)
Bulk Delete Events¶
Delete multiple events in a single request.
Rate Limiting: Bulk tier (10 requests/minute)
Related Endpoints¶
Get Event Detections¶
Get all detections associated with an event.
Get Event Enrichments¶
Get enrichment data for all detections in an event.
Generate Event Clip¶
Generate a video clip for an event.
Data Models¶
EventResponse¶
Source: backend/api/schemas/events.py:61-125
| Field | Type | Description |
|---|---|---|
id | integer | Event ID |
camera_id | string | Normalized camera ID |
started_at | datetime | Event start timestamp |
ended_at | datetime | Event end timestamp |
risk_score | integer | Risk score (0-100) |
risk_level | string | Risk level (low, medium, high, critical) |
summary | string | LLM-generated summary |
reasoning | string | LLM reasoning for risk score |
llm_prompt | string | Full prompt sent to Nemotron |
reviewed | boolean | Review status |
notes | string | User notes |
snooze_until | datetime | Alert snooze timestamp |
detection_count | integer | Number of detections |
detection_ids | array | List of detection IDs |
thumbnail_url | string | URL to thumbnail |
enrichment_status | object | Enrichment pipeline status |
deleted_at | datetime | Soft-delete timestamp |
EnrichmentStatusResponse¶
Source: backend/api/schemas/events.py:27-58
| Field | Type | Description |
|---|---|---|
status | string | Overall status (full, partial, failed, skipped) |
successful_models | array | List of models that succeeded |
failed_models | array | List of models that failed |
errors | object | Model name to error mapping |
success_rate | float | Success rate (0.0 to 1.0) |
Validation Rules¶
Date Range Validation¶
start_datemust be beforeend_date- Dates are normalized to end-of-day for date-only inputs
- Maximum date range: 90 days
Sparse Fieldsets¶
Valid fields for the fields parameter:
id,camera_id,started_at,ended_atrisk_score,risk_level,summary,reasoningreviewed,notes,detection_count,thumbnail_url
Related Documentation¶
- Detections API - Detection data endpoints
- Error Handling - Error response formats
- Request/Response Schemas - Schema details