Outgoing webhook payload
When an alert channel of type Webhook fires, PathWatch sends a
JSON POST (or PUT if you configured it that way) to the URL on
the channel. This page documents the payload shape.
The same shape is shared across all alert events for that channel.
Use the top-level type field to distinguish alerts, recoveries,
and tests.
Headers
Content-Type: application/jsonUser-Agent: PathWatch/1.0X-PathWatch-Signature: sha256=<hex> # only if a secret is setX-PathWatch-Signature is an HMAC-SHA256 of the raw body using the
secret you configured on the channel. Verify it before trusting the
payload — see the example at the bottom of this page.
Any extra headers you set on the channel config are sent alongside these.
Schema
{ "type": "alert", "monitor": { "id": "8c1a...", "name": "Production API", "monitorType": "uptime_http" }, "alertRule": { "id": "f4b2...", "metric": "", "operator": "", "threshold": "" }, "check": { "id": "9d3e...", "status": "timeout", "durationMs": 30000, "errorMessage": "Connection timed out after 30 s", "region": "London, United Kingdom", "regionCity": "London", "regionCountry": "United Kingdom", "regionContinent": "Europe" }, "org": { "id": "0e1f...", "name": "Example Inc." }, "triggeredAt": "2026-06-04T14:32:11.041Z"}Field-by-field
| Field | Type | Notes |
|---|---|---|
type | "alert" | "recovery" | "test" | Distinguishes a triggered alert, a monitor recovering, and the Send-test action. |
monitor.id | UUID | PathWatch-internal monitor id. |
monitor.name | string | The friendly name you set. |
monitor.monitorType | string | E.g. uptime_http, ssl, dns, flow. |
alertRule | object | absent | Present for alert and recovery; absent for type: "test". |
alertRule.id | UUID | The alert rule that fired. |
alertRule.metric, .operator, .threshold | string | Reserved. Currently sent as empty strings. The rule’s logic lives in its scope and condition; a future payload version will expose those. Do not rely on these three values today. |
check | object | absent | Absent for type: "test". |
check.id | UUID | Check result that triggered the alert. |
check.status | "success" | "error" | "timeout" | "degraded" | "skipped" | "runner_unavailable" | The raw check-result status that triggered the notification. |
check.durationMs | integer | absent | How long the check took. |
check.errorMessage | string | absent | Short human-readable failure reason. |
check.region | string | absent | Friendly region label the check ran from (e.g. London, United Kingdom). Never a raw provider id. |
check.regionCity, .regionCountry, .regionContinent | string | absent | Geographic breakdown of the region. |
org.id | UUID | Your organisation id. |
org.name | string | Your organisation’s display name. |
triggeredAt | ISO 8601 string | UTC timestamp the alert fired. |
Verifying the signature
Reject any request whose X-PathWatch-Signature doesn’t match the
HMAC-SHA256 of the raw body using your channel secret. Constant-time
compare to avoid timing attacks.
Node example:
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(body, header, secret) { if (!header?.startsWith("sha256=")) return false; const expected = createHmac("sha256", secret) .update(body) .digest("hex"); const actual = header.slice("sha256=".length); if (expected.length !== actual.length) return false; return timingSafeEqual( Buffer.from(expected, "hex"), Buffer.from(actual, "hex"), );}If the signature header is absent, you didn’t set a secret on the channel — fix that.
Retries
PathWatch retries a failed delivery up to 3 times with exponential
backoff (waits of 1s, then 2s, then 4s). A delivery counts as failed
if your endpoint returns a non-2xx response or the request errors.
Your endpoint should:
- Return any
2xxto acknowledge receipt. - Be idempotent. The same alert can arrive more than once if your endpoint accepts the request but responds slowly enough to look like a failure.
- Use
check.idas the dedup key.
After the 3rd attempt fails, the delivery is marked failed in the alert history. PathWatch does not page you about delivery failures, so monitor your own webhook receiver’s logs.