This page documents the canonical webhook payload — the body you receive when you accept the default shape (no Handlebars template configured). If you’ve templated the body, this page is still useful as the source variable set you can interpolate from.Documentation Index
Fetch the complete documentation index at: https://docs.tallwatch.com/llms.txt
Use this file to discover all available pages before exploring further.
Headers
Every POST includes:| Header | Value | Notes |
|---|---|---|
Content-Type | application/json | Always JSON, even when templated |
User-Agent | Tallwatch/1.0 | Stable string for receiver-side allowlisting |
X-Tallwatch-Event | One of incident.opened, incident.resolved, test | Mirrors event in the body |
X-Tallwatch-Delivery | UUIDv4 | Unique per delivery — use for receiver-side deduplication |
X-Tallwatch-Signature | sha256=<64-hex-chars> | HMAC-SHA256 over the raw request body. Verify against your signing secret. See Signing |
Top-level body
One of
incident.opened, incident.resolved, or test. Always present.When the event happened, in UTC. ISO 8601 with millisecond precision.
The workspace that owns the monitor.
The monitor that fired the event. Always present for incident events. May be
null only for event: "test" triggered without a specific monitor selected.The incident this event belongs to. Present for
incident.opened and incident.resolved. null for event: "test".org object
Stable identifier for the workspace.
The human-readable workspace name as shown in the dashboard.
The URL-safe slug. Resolves to
<slug>.tallwatch.com for the public status page.monitor object
Stable identifier for the monitor.
The display name the user gave the monitor.
One of
http, tcp, icmp, dns, ssl, keyword, heartbeat.For
http and keyword monitors: the URL being checked. For other types: null. To get protocol-specific details for other monitor types, query the Public API — they’re not duplicated into every webhook payload.Tags the user attached to the monitor. Empty array if none. Use these to route alerts on your side (e.g.
prod tag → high-priority lane).incident object
The Tallwatch incident event ID. This is the dispatch dedup key on your receiver side too — same ID never delivered twice.
One of
open, acknowledged, resolved. Matches the event field one-to-one for incident.opened (status: open) and incident.resolved (status: resolved).When the incident first opened. Always present, even on
incident.resolved events.When a user manually acknowledged.
null if never acknowledged. Acknowledgement does NOT auto-fire a webhook event in v1 — this field exists for completeness on the resolved event.When the incident resolved.
null on incident.opened, populated on incident.resolved.Time between
opened_at and resolved_at in seconds. null on incident.opened. Server-computed from clock-skew-safe timestamps.The list of regions that voted the monitor down at the time the event fired. Region codes are
fra1, iad1, hil1, sgp1, syd1. Empty array on incident.resolved.Example: incident.opened
Example: incident.resolved
Example: test
The test alert fires when you click Send test alert on the channel form.
monitor and incident as null so your receiver can branch on event === "test" to short-circuit before processing.
Dedup on your side
Theincident.id is the natural dedup key. Tallwatch’s own alert_dispatches table guarantees we send each (incident_event_id, channel_id) exactly once — but network retries between us and you can still cause a duplicate POST if your receiver times out before responding.
Two options for your receiver:
- Cheap: store the last N delivery IDs (
X-Tallwatch-Deliveryheader) in a TTL’d set. Reject duplicates. - Proper: idempotently upsert on
incident.id+eventso any number of retries converge to one row.
What changes when you use a Handlebars template
The payload becomes whatever your template renders. The variables available inside the template mirror the canonical shape —{{monitor.name}}, {{incident.failing_regions}}, etc. See Templates for the full helper set and example templates.