Skip to content

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/json
User-Agent: PathWatch/1.0
X-PathWatch-Signature: sha256=<hex> # only if a secret is set

X-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

FieldTypeNotes
type"alert" | "recovery" | "test"Distinguishes a triggered alert, a monitor recovering, and the Send-test action.
monitor.idUUIDPathWatch-internal monitor id.
monitor.namestringThe friendly name you set.
monitor.monitorTypestringE.g. uptime_http, ssl, dns, flow.
alertRuleobject | absentPresent for alert and recovery; absent for type: "test".
alertRule.idUUIDThe alert rule that fired.
alertRule.metric, .operator, .thresholdstringReserved. 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.
checkobject | absentAbsent for type: "test".
check.idUUIDCheck result that triggered the alert.
check.status"success" | "error" | "timeout" | "degraded" | "skipped" | "runner_unavailable"The raw check-result status that triggered the notification.
check.durationMsinteger | absentHow long the check took.
check.errorMessagestring | absentShort human-readable failure reason.
check.regionstring | absentFriendly region label the check ran from (e.g. London, United Kingdom). Never a raw provider id.
check.regionCity, .regionCountry, .regionContinentstring | absentGeographic breakdown of the region.
org.idUUIDYour organisation id.
org.namestringYour organisation’s display name.
triggeredAtISO 8601 stringUTC 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 2xx to 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.id as 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.