Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.devhelm.io/llms.txt

Use this file to discover all available pages before exploring further.

DevHelm supports two webhook systems:
  1. Alert channel webhooks — incident notifications routed through notification policies (this page)
  2. Platform event webhooks — subscribe to specific event types for broader automation (see API Reference)

Alert channel webhooks

Send incident notifications to any HTTP endpoint. Plan requirement: Starter or above

Setup

devhelm alert-channels create \
  --name "Custom Webhook" \
  --type webhook \
  --config '{"channelType":"webhook","url":"https://your-app.example.com/webhooks/devhelm","signingSecret":"my-hmac-secret"}'

Configuration

FieldDescriptionRequired
urlWebhook endpoint URL (HTTP or HTTPS)Yes
signingSecretHMAC signing secret for payload verificationNo
customHeadersAdditional HTTP headers to includeNo
Custom headers cannot use the X-DevHelm-* prefix or override Content-Type.

Verifying signatures

When a signing secret is configured, DevHelm includes a signature header:
X-DevHelm-Signature: t=1712956800;v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
To verify:
  1. Extract the t (timestamp) and v1 (signature) values
  2. Compute HMAC-SHA256(signingSecret, t + ":" + requestBody)
  3. Compare the computed signature with v1
  4. Optionally reject requests where t is too old (replay protection)
The signed string uses a literal colon (:) between the timestamp and the raw request body — no quoting, no escaping. Use the raw bytes of the HTTP request body (do not re-serialise the parsed JSON, since key ordering or whitespace would change the hash).

Platform event webhooks

For broader event coverage beyond incident notifications, use the platform webhook system at /api/v1/webhooks.

Available event types

Monitoring events:
  • monitor.created, monitor.updated, monitor.deleted
  • incident.created, incident.resolved, incident.reopened
Status data events:
  • service.status_changed, service.component_changed
  • service.incident_created, service.incident_updated, service.incident_resolved

Envelope format

Every platform event webhook delivery POSTs the following envelope as the request body:
{
  "id": "11111111-1111-1111-1111-111111111111",
  "type": "incident.created",
  "apiVersion": "2026-01",
  "createdAt": "2026-04-24T12:34:56Z",
  "data": {
    // Event-specific payload
  }
}
  • id — unique event ID. Use this for idempotent processing: the same id is sent on every retry, so receivers can deduplicate by storing IDs they’ve already processed.
  • type — event type identifier (matches the X-DevHelm-Event header).
  • apiVersion — pinned envelope/payload version. Increments only when the schema changes incompatibly. Receivers should branch on this value if they need to support multiple versions during a migration.
  • createdAt — UTC timestamp (ISO 8601 with Z suffix) of when DevHelm originated the event.
  • data — the event-specific payload. Shape depends on type.

Outgoing headers

HeaderDescription
X-DevHelm-EventEvent type (e.g., incident.created)
X-DevHelm-DeliveryUnique delivery ID
X-DevHelm-Signaturet=<timestamp>;v1=<hmac-sha256>

Managing webhook endpoints

# Create a webhook endpoint
curl -X POST https://api.devhelm.io/api/v1/webhooks \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/events",
    "events": ["incident.created", "incident.resolved"]
  }'

# Test a webhook
curl -X POST https://api.devhelm.io/api/v1/webhooks/<id>/test \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"

# List deliveries
curl https://api.devhelm.io/api/v1/webhooks/<id>/deliveries \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"

Troubleshooting

  1. Check that your endpoint returns a 2xx status code within the timeout
  2. Review delivery history: GET /api/v1/webhooks/<id>/deliveries
  3. Verify your endpoint accepts POST requests with Content-Type: application/json
  1. Make sure you’re using the correct signing secret
  2. Use the raw request body for HMAC computation (before any JSON parsing)
  3. The signature format is t=<unix-timestamp>;v1=<hex-hmac> — parse both values