Automation
Signed webhooks
A webhook: channel delivers a JSON POST to your endpoint
on every state change, signed with HMAC-SHA256 so you can verify it came from Alwaysbeat.
Setup
Add a channel of the form webhook:https://your-endpoint to a check (see
Notifications). Only http/https
URLs with a public host are accepted — requests to private or internal addresses are refused.
The request
Deliveries are POST with Content-Type: application/json and a
User-Agent of dead-mans-fingers-webhook/1. The body is:
{
"event": "check.state_changed",
"check_id": "3f8a1c2e-...",
"name": "nightly-db-backup",
"status": "down", // new state
"previous": "up", // prior state
"reason": "missed", // why it changed
"account_id": "...",
"at": "2026-07-20T03:35:00Z" // RFC 3339, UTC
}
Respond with any 2xx to acknowledge. Non-2xx responses are retried with backoff;
4xx (other than 429) are treated as permanent and not retried.
Verifying the signature
Every delivery carries an X-DMF-Signature header:
X-DMF-Signature: t=1753000500,v1=<hex-hmac-sha256>
where:
t— the Unix timestamp (seconds) when the request was signed.v1— the hex-encoded HMAC-SHA256 of the string"<t>.<raw-request-body>", keyed with your webhook signing secret.
To verify: recompute the HMAC over t, a literal ., and the exact raw
body, then compare in constant time. Reject the request if it doesn't match, and reject stale
timestamps to prevent replays.
# Python (Flask)
import hmac, hashlib, time
def verify(request, secret):
header = request.headers["X-DMF-Signature"]
parts = dict(p.split("=", 1) for p in header.split(","))
ts, sig = parts["t"], parts["v1"]
signed = f"{ts}.".encode() + request.get_data() # raw body, unparsed
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
return False
if abs(time.time() - int(ts)) > 300: # reject >5 min old
return False
return True