Skip to content

Payload

This page describes the JSON body a webhook channel receives — see Webhooks for the headers and the signature that authenticates it. Other channel types render their own text and do not expose this body directly.

{
"event": "opened",
"incident": {
"id": "…",
"cause": "…",
"openedAt": "2026-08-15T12:00:00.000Z",
"url": "https://app.wirewatch.io/incidents/…"
},
"monitor": { "name": "…", "locations": ["…"] },
"severity": { "level": "full", "downLocations": ["…"] }
}

Stable — safe to build logic on:

  • event — one of opened, severity_changed, resolved. See below for what each carries.
  • incident.id — the incident’s identifier. Stable across every event for the same incident; use it to correlate opened → severity_changed → resolved.
  • incident.openedAt — ISO 8601, when the incident opened. Unchanged across events for the same incident.
  • incident.url — a permalink to the incident in the app.
  • monitor.name, monitor.locations — the monitor’s configured name and probe locations.
  • severity.downLocations — the locations currently reporting down. An empty array, never omitted, when there is nothing to report — a heartbeat monitor has no probe locations at all.

Present only when there is a scope to claim:

  • severity.level — full or partial. Omitted (not null) on the events where WireWatch has no scope claim to make.

incident.cause is human-readable text explaining why the incident opened. It is not an enum, and nothing alongside it tells you which of two different vocabularies you got. One vocabulary is detection reasons (no_data, quorum_confirmed, heartbeat_missed, and others); the other is probe-level error classes (dns_error, connection_timeout, and others — including values a customer’s own agent can emit that WireWatch has never seen). Both are used, for different incidents, with nothing marking which one you are reading.

This is deliberate honesty, not an oversight. An earlier version of this documentation enumerated the values, and a customer who built logic against that list received the literal string quorum_confirmed in a rendered alert the day the real vocabulary grew past what was documented. Publishing a list is an implicit promise to keep it complete, and this field cannot keep that promise.

The cost, stated plainly: if you want to branch on why an incident opened — routing PagerDuty severity by cause, for example — there is currently no supported way to do it from this payload. cause is for a human to read, not for a program to switch on. A machine-readable, discriminated cause is a product change this page cannot promise into existing today.

Event What’s new
opened The incident just started. severity reflects the scope observed at open.
severity_changed The incident’s scope changed since opened — severity.level and severity.downLocations reflect the NEW scope, not the old one.
resolved The incident is closed. severity reflects the last known scope before recovery; a resolved event carries no new failure information.

Every event for the same incident carries the same incident.id, so you can group them without depending on delivery order.