Verifying webhooks
Every webhook bootload sends is signed, so your endpoint can confirm it
really came from bootload and wasn't tampered with or replayed. When you create a
webhook you get a signing secret (shown once, starting with whsec_) — keep
it safe and verify every delivery against it.
Standard Webhooks (recommended)
Deliveries follow the Standard Webhooks spec, so you can verify them with an off-the-shelf library. Each request carries:
webhook-id— a unique id for this deliverywebhook-timestamp— the Unix time it was signedwebhook-signature—v1,<base64 HMAC-SHA256>
The signature is the HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{body},
keyed by the bytes of your secret (the base64 after whsec_). Reject the request
if the signature doesn't match, or if the timestamp is more than a few minutes
old (that's your replay protection).
Most languages have a ready-made verifier:
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.BOOTLOAD_WEBHOOK_SECRET); // "whsec_…"
const payload = wh.verify(rawBody, {
"webhook-id": req.headers["webhook-id"],
"webhook-timestamp": req.headers["webhook-timestamp"],
"webhook-signature": req.headers["webhook-signature"],
});
// throws if invalid — otherwise `payload` is the trusted event
Always verify against the raw request body, before any JSON parsing re-serializes it.
Legacy header
For backwards compatibility, deliveries also include the original
X-Bootload-Signature: sha256=<hex> header — an HMAC-SHA256 of the raw body
keyed by the full secret string. It has no timestamp (no replay protection) and
is deprecated; move to the Standard Webhooks headers above. It will be
removed in a future release.
Also useful
X-Bootload-Event/webhook-ididentify the event type and delivery.- Rotate the secret any time from the portal (Webhooks → rotate secret) or
bootloadCLI — the old secret stops validating immediately, so update your endpoint in the same change.