Skip to content

Webhook event types

This page lists every webhook event type the NovaVMS platform currently emits. Subscribe to an event by including its name in the events array when you create or update a webhook.

Event types

Event typeSinceStatus (audit 2026-05-23)DescriptionSample payload
alertv1.0LiveAn alert rule matched an incoming event and fired. Carries the six current alert display/identity fields.alert
eventv1.0Rejected (B-7)Reserved for a future per-event publisher that does not exist yet. The cloud now returns HTTP 400 when this value is submitted to POST /api/v1/webhooks.event
camera_statusv1.0Rejected (B-7)Reserved for a camera-online/offline edge-triggered publisher that has not been wired. The cloud now returns HTTP 400 when submitted.camera_status
gateway_statusv1.0Rejected (B-7)Reserved for a gateway-online/offline edge-triggered publisher that has not been wired. The cloud now returns HTTP 400 when submitted.gateway_status

Only alert is currently accepted by POST /api/v1/webhooks. Submitting any other value (including the three reserved entries above) returns 400 Validation. The reserved rows are documented here so payload shapes are pinned in advance — they will become live once the publishers ship, at which point this status column will flip.

Event types that sound plausible (event.created, alert.fired, clip.exported, user.invited, user.activated) are not emitted by v1.x. Future event types will be added here with the version in which they first ship.

Sample payloads

Every delivery is wrapped in the same envelope:

{
"event_type": "<event-type>",
"timestamp": "2026-04-21T14:30:00Z",
"data": { }
}

timestamp is RFC 3339 UTC. X-Webhook-ID is the webhook configuration UUID; the current JSON body does not include a webhook_id field. The per-event data shapes follow.

alert

The current alert wire payload is intentionally narrow. On the compiled-rule fanout path, event_id, rule_name, and description are populated; alert_id, camera_name, and severity are currently serialized as empty strings. It does not embed the rule’s D95 predicates, legacy custom_tags, or a nested event object.

{
"event_type": "alert",
"timestamp": "2026-04-21T14:30:00Z",
"data": {
"alert_id": "",
"rule_name": "Entrance person after hours",
"camera_name": "",
"event_id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"severity": "",
"description": "Entrance person after hours",
"is_test": false
}
}

is_test:true is set when the payload originates from POST /api/v1/webhooks/{id}/test (use this flag to discard tests in production handlers). For compiled alerts, use event_id as the stable deduplication key and resolve additional rule or event details through the authenticated REST API.

event

Event payloads are D95 universal taxonomy (event_category, trigger_topic, trigger_source). The legacy trigger_type field is no longer present on event records (events.trigger_type was removed in migration 000053).

{
"event_type": "event",
"timestamp": "2026-04-21T14:30:00Z",
"webhook_id": "2d1e9c8b-7a6f-5e4d-3c2b-1a0f9e8d7c6b",
"data": {
"event_id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"camera_id": "8f2b3a71-0c4e-4b5f-9d1a-2e7c3a4b5d6f",
"camera_name": "Lobby Camera",
"site_name": "Headquarters",
"event_category": "motion",
"trigger_topic": "tns1:VideoSource/MotionAlarm",
"trigger_source": "onvif",
"raw_source": "hikvision",
"raw_data": {"State": true, "ChannelID": 1},
"triggered_at": "2026-04-21T14:29:58Z",
"description": "Person detected at entrance",
"tags": ["person", "entrance"],
"ai_severity": "info",
"snapshot_url": "https://media.novavms.io/snap/3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f.jpg"
}
}

Universal ONVIF event payloads (D95)

The raw_source and raw_data fields expose the vendor-specific event payload that produced this normalized event, so subscribers can inspect details the gateway classifier did not preserve in tags or description. raw_source identifies the producer (camera vendor slug or software/manual/vlm); raw_data is the un-normalized JSON object the gateway received.

A Tapo tampering-scene event illustrates the shape:

{
"event_type": "event",
"timestamp": "2026-04-21T14:31:00Z",
"webhook_id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d",
"data": {
"event_id": "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
"camera_id": "8f2b3a71-0c4e-4b5f-9d1a-2e7c3a4b5d6f",
"camera_name": "Storage Room",
"site_name": "Headquarters",
"event_category": "tampering_scene",
"trigger_topic": "tns1:VideoSource/ImageTooDark",
"trigger_source": "onvif",
"raw_source": "tapo",
"raw_data": {"Channel": "0", "TamperState": "tooDark", "Threshold": 12},
"triggered_at": "2026-04-21T14:30:58Z",
"description": "Image too dark on Storage Room",
"tags": ["tamper", "low_light"],
"ai_severity": "warning"
}
}

A Hikvision shelter / cover-camera tamper event surfaces with a different trigger_topic and raw_data shape:

{
"event_type": "event",
"timestamp": "2026-04-21T14:32:00Z",
"webhook_id": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"data": {
"event_id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"camera_id": "8f2b3a71-0c4e-4b5f-9d1a-2e7c3a4b5d6f",
"camera_name": "Storage Room",
"site_name": "Headquarters",
"event_category": "tamper",
"trigger_topic": "tns1:RuleEngine/TamperDetector/Tamper",
"trigger_source": "onvif",
"raw_source": "hikvision",
"raw_data": {"eventType": "shelteralarm", "channelID": 1, "active": true},
"triggered_at": "2026-04-21T14:31:58Z",
"description": "Tamper detected on Storage Room",
"tags": ["tamper"],
"ai_severity": "warning"
}
}

See Universal ONVIF events for the full topic ladder, classifier rules, and per-vendor raw_data shapes.

camera_status

{
"event_type": "camera_status",
"timestamp": "2026-04-21T14:30:00Z",
"webhook_id": "5f6a7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c",
"data": {
"camera_id": "8f2b3a71-0c4e-4b5f-9d1a-2e7c3a4b5d6f",
"camera_name": "Lobby Camera",
"site_name": "Headquarters",
"status": "offline",
"previous_status": "online",
"offline_since": "2026-04-21T14:25:00Z"
}
}

gateway_status

{
"event_type": "gateway_status",
"timestamp": "2026-04-21T14:30:00Z",
"webhook_id": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"data": {
"gateway_id": "4d5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f90",
"gateway_name": "Site A Gateway",
"site_name": "Headquarters",
"status": "offline",
"previous_status": "online",
"cameras_affected": 12
}
}

Signature header

Every delivery carries an HMAC-SHA256 signature in the X-Webhook-Signature header, computed over the raw request body with the webhook’s secret. See Verify a webhook signature for code samples in TypeScript, Python, and Go.

Delivery semantics

  • At-least-once. A compiled alert may arrive more than once after transient network failures. Deduplicate it on data.event_id; data.alert_id is empty on that path. X-Webhook-ID is the webhook UUID (constant per webhook), not a per-delivery identifier. See Setup for the header-vs-body rule.
  • Retry policy. A delivery makes one initial attempt plus up to three retries after 1, 5, and 30 seconds. A 401 or 403 short-circuits the remaining retries for that delivery attempt.
  • Timeout. Each delivery attempt has a 60-second context timeout server-side; receivers should still return 2xx within 10 seconds to leave headroom.
  • Auto-disable. After repeated consecutive failed deliveries the webhook is disabled (enabled=false); admins re-enable it from /settings/webhooks. See Webhook delivery failures.
  • Ordering. Deliveries are not strictly ordered. Use the envelope timestamp to reorder on the receiver.