Webhooks
Gaard webhooks let you receive classification results as an HTTP POST to your own endpoint as soon as processing is finished.
For integrators, the main idea is simple:
- your system sends a video to Gaard
- Gaard classifies it asynchronously
- when the final result is available, Gaard posts the result JSON to your webhook URL
What a webhook sends
Section titled “What a webhook sends”Gaard currently sends one webhook event type: the final classification result.
The webhook payload uses the same JSON shape as the result returned by:
GET /api/result/{id}POST /api/classify?sync=true
That means you can usually reuse the same parser for both polling and webhook-based integrations.
How it works
Section titled “How it works”- Your application submits a video to
POST /api/classify. - Gaard accepts the job and processes it asynchronously.
- After classification is completed and the result is persisted, Gaard sends an HTTP
POSTrequest to each webhook configured for the flow. - Your endpoint receives the result payload and can trigger downstream actions such as incident creation, alarm enrichment, or archival.
Set up a webhook in Gaard
Section titled “Set up a webhook in Gaard”In the Gaard application:
- Open the integrations section. Platform integrations
- Create a new
Webhookintegration. - Select the flow that should trigger the webhook.
- Enter the destination URL of your receiver.
- Save the integration.
- Submit a test classification and verify that your endpoint receives the payload.
If you need to send the same result to multiple systems, create multiple webhook integrations.
HTTP request format
Section titled “HTTP request format”Gaard sends:
- Method:
POST - Header:
Content-Type: application/json - Body: classification result JSON
Gaard does not currently add custom authentication headers or a signature header. If your receiver requires authentication, protect it at your edge, for example with a secret URL path, a reverse proxy, or another mechanism you control.
Example payload
Section titled “Example payload”{ "id": "6662f5c1f897618de43f0bbd", "status": { "classify": "done", "video": "done" }, "parent_id": "000000000000000000000000", "camera_id": "134188-VI08", "analyse_id": 3373550353, "tenant": "tenant", "duration": 2968236, "duration_seconds": 2, "model": "noname", "version": "2.0.16123", "error_code": 0, "error_msg": "", "risk": "intrusion", "labels": ["intrusion", "person"], "result": "classified", "scores": { "flag": 0.049, "plant": 0.03, "web": 0.009, "NOTHING": 0.0005, "intrusion": 0.973, "person": 0.973, "rain": 0.002, "spider": 0.007, "text": 0.0006, "wind": 0.021, "animal": 0.035, "other": 0.028, "vehicule": 0.101 }, "video": { "videoname": "video.mov", "filename": "video.mov", "filesize": 786800, "specs": { "height": 320, "original.width": 640, "duration": 4.217772, "fps": 3.08, "nframes": 13, "original.fps": 3, "original.height": 360, "original.nframes": 12, "width": 568 } }, "metadata": { "camera_id": "VI08", "site_id": 134188 }, "created_at": "2024-05-14T16:13:37.156+02:00", "started_at": "2024-05-14T16:13:37.156+02:00"}Payload field notes
Section titled “Payload field notes”| Field | Type | Notes |
|---|---|---|
id | string | Stable classification identifier. Use it as your primary correlation key. |
status | object | Final processing state for classification and video annotation. |
camera_id | string | Camera identifier derived from metadata. |
analyse_id | int | Original analysis identifier when provided by the sender. |
tenant | string | Gaard tenant that produced the result. |
risk | string | High-level outcome such as safe, danger, or intrusion. |
labels | string[] | Labels derived from the score set. |
result | string | Raw engine result string such as classified. |
scores | object | Per-label confidence scores. |
video | object | Video file name, size, and technical specs. |
metadata | object | Original metadata submitted with the classification request. |
created_at | string | When the classification task was created. |
started_at | string | When processing started. |
For the full field reference, see Response structure and Classification result.
Latency and delivery behavior
Section titled “Latency and delivery behavior”Webhook delivery is tied to classification completion.
- Gaard does not send the webhook when the job is merely accepted.
- Gaard sends the webhook after the classification result is stored and post-processing is complete.
- In practice, webhook timing is usually very close to the moment the result becomes available from
GET /api/result/{id}.
There is no separate webhook queue or scheduled batch window. End-to-end webhook latency is therefore:
Σ(t) = classify + post-processing + networkGaard does not currently publish a fixed webhook latency SLA, because classification duration depends on the video, model, runtime load, and network distance to your receiver.
Reliability model
Section titled “Reliability model”Webhook delivery is currently best effort.
- Gaard sends one HTTP
POSTper configured webhook endpoint. - Gaard does not currently implement automatic retries.
- Gaard does not currently treat non-
2xxHTTP responses as retryable delivery failures.
Because of that, your receiver should:
- accept the request quickly
- return a response immediately after basic validation
- move heavier work to an internal queue or background worker
- store the payload
idso your processing is idempotent
Receiver recommendations
Section titled “Receiver recommendations”To make your integration robust:
- Accept
application/jsonrequests. - Validate that
id,tenant, and the fields you depend on are present. - Use the payload
idas your deduplication key. - Treat
error_code != 0as a completed result with an error, not as a transport failure. - Keep your webhook endpoint fast and asynchronous.
- Log the full payload during your initial rollout so you can confirm which metadata fields are present in your environment.
Example response from your endpoint
Section titled “Example response from your endpoint”Your endpoint can return a minimal success response such as:
HTTP/1.1 200 OKContent-Type: application/json
{"ok":true}When to use webhooks vs polling
Section titled “When to use webhooks vs polling”Use webhooks when:
- you want near-real-time downstream processing
- you already operate an HTTP service that can receive callbacks
- you want to avoid repeated polling for result availability
Use polling with GET /api/result/{id} when:
- inbound HTTP callbacks are not possible in your environment
- you need explicit control over fetch timing
- you want a simpler first integration before moving to event-driven delivery