Outgoing Webhooks
Manage outgoing webhook subscriptions for organization events.
Webhook signing
When an event fires, StatusPal POSTs a JSON payload to your configured outgoing_webhook.url. Every delivery carries the following headers:
Content-Type
application/json
User-Agent
StatusPal-Webhooks/1.0
X-StatusPal-Event
The event name (service.status_changed, notice.created, or notice.updated)
X-StatusPal-Delivery
A per-attempt UUID, use it to dedupe retried deliveries
X-StatusPal-Signature
Stripe-style signature: t=<unix_ts>,v1=<hex_hmac>
The signature covers "#{t}.#{raw_body}", signed with HMAC-SHA256 using the webhook's plaintext signing secret (the whs_… value returned once when the webhook was created or its secret was rotated). Verify it like this:
parsed = parse_header("X-StatusPal-Signature") # → { t: <int>, v1: <hex> }
signed = `${parsed.t}.${raw_body}`
digest = HMAC_SHA256(secret, signed)
if (Date.now() / 1000 - parsed.t > 300) reject # 5-minute tolerance recommended
if (!constant_time_eq(digest, parsed.v1)) rejectDelivery retries
Each event is delivered up to 3 times with exponential backoff: 1s, 2s, 4s between attempts. Any 2xx response is treated as success; any other status, a timeout (5s open / 10s read), or a network error triggers the next retry. After the third failure the delivery is dropped.
Organization API key — issue one via the Rails console (management UI coming soon)
120OK
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
GET /api/v1/outgoing_webhooks HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"data": [
{
"id": "text",
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created",
"notice.updated"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
],
"last_triggered_at": null,
"last_attempted_at": null,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}
],
"meta": {
"current_page": 1,
"per_page": 1,
"total_count": 1,
"total_pages": 1
}
}Creates a new outgoing webhook. The response includes the plaintext signing secret exactly once — store it immediately, it cannot be retrieved later. Use POST /outgoing_webhooks/{id}/regenerate_secret to rotate.
Organization API key — issue one via the Rails console (management UI coming soon)
Ops alertshttps://hooks.example.com/statuspaltruetrueRequired when all_status_pages is false. Subdomains of the
status pages this webhook should fire for. Unknown subdomains
cause a 422.
["prod-status","eu-status"]Created
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
Validation failed
POST /api/v1/outgoing_webhooks HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 185
{
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
]
}{
"data": {
"id": "text",
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created",
"notice.updated"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
],
"last_triggered_at": null,
"last_attempted_at": null,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z",
"secret": "whs_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}
}Organization API key — issue one via the Rails console (management UI coming soon)
TypeID-prefixed identifier (e.g. wbk_01h2x...)
OK
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
Resource not found
GET /api/v1/outgoing_webhooks/{id} HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"data": {
"id": "text",
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created",
"notice.updated"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
],
"last_triggered_at": null,
"last_attempted_at": null,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}
}Organization API key — issue one via the Rails console (management UI coming soon)
TypeID-prefixed identifier (e.g. wbk_01h2x...)
Deleted
No content
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
Resource not found
DELETE /api/v1/outgoing_webhooks/{id} HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Organization API key — issue one via the Rails console (management UI coming soon)
TypeID-prefixed identifier (e.g. wbk_01h2x...)
OK
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
Resource not found
Validation failed
PATCH /api/v1/outgoing_webhooks/{id} HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 152
{
"name": "text",
"url": "https://example.com",
"events": [
"service.status_changed"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"text"
]
}{
"data": {
"id": "text",
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created",
"notice.updated"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
],
"last_triggered_at": null,
"last_attempted_at": null,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z"
}
}Replaces the webhook's signing secret with a freshly generated value. The new plaintext secret is returned in this response only — it is not stored in cleartext and cannot be retrieved later.
Organization API key — issue one via the Rails console (management UI coming soon)
TypeID-prefixed identifier (e.g. wbk_01h2x...)
OK
Missing or invalid API key
The account is pending activation. A newly created account must be activated by an administrator before its API key can be used.
Resource not found
POST /api/v1/outgoing_webhooks/{id}/regenerate_secret HTTP/1.1
Host: next.statuspal.io
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"data": {
"id": "text",
"name": "Ops alerts",
"url": "https://hooks.example.com/statuspal",
"events": [
"notice.created",
"notice.updated"
],
"enabled": true,
"all_status_pages": true,
"status_page_subdomains": [
"prod-status",
"eu-status"
],
"last_triggered_at": null,
"last_attempted_at": null,
"created_at": "2026-01-01T00:00:00.000Z",
"updated_at": "2026-01-01T00:00:00.000Z",
"secret": "whs_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}
}Last updated