Changelog

Standard Webhooks

In short

Sign every delivery attempt, and verify webhooks from any sender that uses the spec


Event Gateway now signs and verifies webhooks with Standard Webhooks, an open specification for webhook signatures. A signed request carries a webhook-id, a webhook-timestamp and a webhook-signature, which is an HMAC-SHA256 of the ID, timestamp and body made with a whsec_ secret. A receiver checks it with one of the spec's libraries.

Sign deliveries to your endpoints. Choose Standard Webhooks as the authentication method on an HTTP, CLI or Mock API destination, and enter your endpoint's secret. Event Gateway signs every attempt again, retries included, so a retry sent an hour later still passes an endpoint that rejects timestamps more than five minutes old. The webhook-id stays the same across attempts, so your endpoint can deduplicate on it. It's the original sender's webhook-id when the request had one, and otherwise the Hookdeck event ID.

Verify webhooks from any sender that uses the spec. Webhook and HTTP sources verify Standard Webhooks signatures, next to HMAC, Basic Auth and API key verification, so a sender that signs this way doesn't need a dedicated source type. A request passes when any v1 signature in its webhook-signature header matches, so a sender can rotate its secret by signing with both. A request with a bad signature is rejected with VERIFICATION_FAILED. See Standard Webhooks verification. The MCP_EVENTS source type verifies the same signatures for deliveries from an MCP server.

Limits. A destination signs with one secret, and rotation isn't available yet. A webhook-id that contains a period fails the attempt with DESTINATION_AUTH_FAILED, and nothing is sent. A transformation can rewrite such an ID. Asymmetric v1a signatures aren't supported for signing or verifying. Source verification happens after Event Gateway accepts the request, so a sender with a bad signature gets the source's usual response, not a 401. The Hookdeck CLI can't set Standard Webhooks on a destination yet, so use the dashboard or the API.

Read the docs