Signed webhooks
Connect an endpoint
Open Integrations, find Signed webhooks, and choose Set up integration. Add a public HTTPS endpoint on port 443 and select confirmed outages, recoveries, or both. Save the signing secret shown after creation: it cannot be retrieved later. Use Connected → Test to send a webhook.test event.
Endpoints must resolve only to public IPv4 addresses. Private networks, IPv6, URL credentials, fragments, and redirects are not supported. Endpoint credentials and signing secrets are encrypted at rest.
Verify a delivery
Requests are JSON POSTs with three headers:
X-Uptime-Id: stable notification identifier; deduplicate this across retries.X-Uptime-Timestamp: Unix timestamp in seconds for this attempt.X-Uptime-Signature:v1=followed by the hexadecimal HMAC-SHA256 digest oftimestamp + "." + rawBody, using your signing secret exactly as displayed.
Read the raw body before JSON parsing, reject timestamps more than five minutes old (or materially in the future), and compare signatures in constant time. Do not log the secret.
import { createHmac, timingSafeEqual } from 'node:crypto'
export function verifyWebhook(rawBody, timestamp, signature, secret) {
if (!/^\d+$/.test(timestamp ?? '')) return false
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false
const expected = Buffer.from('v1=' + createHmac('sha256', secret)
.update(timestamp + '.').update(rawBody).digest('hex'))
const actual = Buffer.from(signature ?? '')
return actual.length === expected.length && timingSafeEqual(actual, expected)
}
Event payload
{
"id": "notification-uuid",
"type": "incident_confirmed",
"createdAt": "2026-09-05T12:00:00.000Z",
"data": {
"monitor": "Checkout API",
"target": "https://api.example.com/health",
"summary": "Regional failure threshold reached",
"openedAt": "2026-09-05T12:00:00.000Z",
"resolvedAt": null
}
}
Incident types are incident_confirmed and incident_resolved. Test events have type webhook.test and a data.message string. createdAt reflects the incident opening or recovery time. Treat the notification ID as opaque.
Return any 2xx response within ten seconds. Failed incident deliveries retry up to five total attempts with exponential backoff (5, 10, 20, 40 seconds between attempts). Duplicate deliveries are possible. Tests run once and report their result immediately. Pausing or removing a destination stops future deliveries; already in-flight requests may finish. To replace a lost or compromised signing secret, create a replacement destination and remove the old one.