When webhooks fire
How status-change deliveries work and what to expect from the receiver.
When you create a notification channel of type webhook, Obzerv POSTs a JSON body to your URL on every monitor status change (up → down or down → up).
Maintenance windows suppress deliveries: while inside an active window, status changes for the affected monitors do not fire webhooks.
Delivery details
| Property | Value |
|---|---|
| Method | POST |
| Content-Type | application/json |
| Headers | Content-Type: application/json, X-Obzerv-Signature — see payload reference. |
| Timeout | ~10 seconds. Slower endpoints are considered failed. |
| Retries | Confirmed incident events are stored durably; transient delivery failures can be retried. |
| Ordering | Do not rely on arrival order, especially when a delivery is retried. |
| Idempotency | Duplicate deliveries are possible. Deduplicate by (monitor_id, timestamp, event) using the payload fields. |
Accept valid signed requests promptly and process them idempotently. A retry may arrive after a newer event; compare event timestamps when updating state.
SSRF protection
Webhook URLs are validated when the channel is created and again at delivery. The following targets are rejected:
localhost,127.0.0.0/8,::1- Private IPv4:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - Private IPv6:
fc00::/7,fe80::/10 - Cloud metadata:
169.254.169.254
If you genuinely need deliveries to a private network, expose your endpoint via a tunnel (ngrok, Cloudflare Tunnel) and put the public URL in the channel.
Authenticating the request
Every delivery carries an X-Obzerv-Signature: sha256=<hex> header — an HMAC-SHA256 of the raw body using your channel's signing secret. Verify it on every request to confirm the payload is genuine. Full code samples in Verify webhook signatures.
Each webhook channel has its own per-channel HMAC-SHA256 signing secret, returned once on POST /notification-channels as signing_secret. See Verify webhook signatures.
Next
Payload reference → — exact JSON shape on disk.