Outbound webhooks
Event payload shape, HMAC signature verification, retry policy.
When a channel of type webhook fires, Pulse POSTs a JSON payload to the configured URL with these headers:
Content-Type: application/jsonUser-Agent: PulseNotifier/<version>X-Pulse-Event: incident.opened | incident.resolved | alert.firing | ...X-Pulse-Signature: t=<unix>,v1=<hex>X-Pulse-Delivery: <uuid>Verifying the signature
Section titled “Verifying the signature”Concatenate <timestamp>.<raw body>, HMAC-SHA256 with the channel’s secret, hex-encode, compare to the v1 field. Reject if the timestamp is older than 5 minutes (replay defense).
import hmac, hashlib, time
def verify(secret, header, body, max_age=300): parts = dict(p.split("=", 1) for p in header.split(",")) if abs(time.time() - int(parts["t"])) > max_age: return False expected = hmac.new(secret.encode(), f"{parts['t']}.{body}".encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(expected, parts["v1"])Retry policy
Section titled “Retry policy”- Attempt 1: immediately
- Attempt 2: +30s
- Attempt 3: +2m
- Attempt 4: +5m
- Attempt 5: +10m
After 5 failed attempts the delivery is dropped. Failures surface in Settings → Channels → <channel> → Recent deliveries.
Event payload shape
Section titled “Event payload shape”{ "event": "incident.opened", "delivery_id": "01HN...", "occurred_at": "2026-05-19T01:23:45Z", "org_id": "...", "data": { "incident": { "id": "INC-104", "title": "...", "severity": "P1", "status": "investigating" } }}