Skip to main content
An endpoint’s URL is its credential. Turn on signature verification and the endpoint also checks the signature your provider puts on every request. Hookie verifies it over the raw request bytes before anything is stored or counted against your quota, on the endpoint’s public URL and on /v1/webhooks/{key}/{slug} alike. A request that fails gets 401 and is neither stored nor counted. The body says what went wrong:
Every refusal is written to your audit log as ingest_signature_rejected, with the scheme and reason, and appears in the endpoint’s Activity as signature_required, signature_invalid or signature_stale. Neither ever includes the secret or the signature that was sent. Your provider’s delivery log shows the 401 body, so it tells you which of the three went wrong. Where the check sits: a provider’s URL-verification handshake (Slack, Meta, Microsoft Graph, Zoom, Twitch) is answered first, and a body Hookie cannot read is refused with 400, 415 or 422 as usual. The signature is checked next, before duplicate detection, the quota and the store.

Schemes

Timestamps. stripe, slack and standard_webhooks sign a timestamp, and a request more than 5 minutes from now is refused as stale_timestamp. Set tolerance_seconds (a whole number from 30 to 86400) to change the window. It applies to those three schemes only; the others sign no timestamp, and sending it with them is refused with 400. Generic HMAC. For a sender with its own scheme, hmac takes: These settings apply to hmac only. The other schemes have fixed headers, so sending one of them with another scheme is refused with 400, as is any setting Hookie does not know. What is stored is always what is used.
Don’t turn verification on for an endpoint that a browser form posts to. A browser signs nothing, so every submission would get 401. The same goes for an endpoint with live traffic from a sender that does not sign yet: from the moment you save, its requests are refused.

Turn it on

In the console, open the endpoint’s Edit… (or Add endpoint). Choose the provider under Signature verification and paste its signing secret. The secret is encrypted at rest and never shown again. The endpoint card shows only the scheme. Over the API, pass verification when you create the endpoint or in a PATCH:
A generic HMAC sender:
The secret is write-only. It is up to 512 characters; a Standard Webhooks secret is whsec_ followed by base64, or the base64 alone. No response, audit entry, log or workspace export ever contains it. Responses describe verification as:
has_secret says whether a secret is held, and previous_secret_expires_at is when a rotated-out secret stops verifying, or null outside a rotation. The list, GET webhooks/{id} and a create’s webhook object all carry it.
  • Change settings without pasting the secret again: send the same scheme with no secret. Switching to a different scheme needs that provider’s secret.
  • Replace the secret at once: send a new secret in the PATCH. The old one stops verifying immediately. To keep it working while your provider switches over, rotate instead.
  • Turn verification off: send {"scheme": "none"}. The stored secret is deleted.
Any change to verification in a PATCH also ends a rotation’s overlap. A new version of an endpoint starts with its parent’s verification. Project export, import and clone carry an endpoint’s verification as its scheme and settings, never the secret. The copy is created with that scheme and no secret, so it refuses every request with 401 until you set one (the endpoint’s Edit → Verification, or PATCH with {"verification": {"scheme": "…", "secret": "…"}}). It never starts out weaker than the endpoint it was copied from. The import or clone response lists these endpoints under needs_verification_secret, and hookie apply says the same for each one it creates. To create an endpoint this way yourself, send "without_secret": true in place of secret on create. The Stripe, GitHub and Shopify source presets (GET /admin/api/source-presets) name their scheme in verification_scheme.

Rotating the secret

When your provider rolls its signing secret, rotate it here too. The secret it replaces keeps verifying through an overlap, so events signed either way are kept while the provider switches:
overlap_hours is 0 to 720 and defaults to 24. With 0, the old secret stops at once. Hookie keeps one previous secret, so rotating again inside an overlap ends the older one. An endpoint that does not verify signatures answers 409: turn verification on first. The rotation is recorded in the audit log as rotate_webhook_verification_secret, with the overlap and never either secret. In the console, choose Rotate signing secret… in the endpoint’s menu, paste the New signing secret, and choose how long to Keep accepting the current secret for: an hour, a day (the default), a week or 30 days, or end it now.

Agents and the CLI

All three tools need hookie:write. A connected agent is told to ask you for the provider’s secret rather than invent one.

Provider notes

Stripe

Stripe signs with the endpoint’s signing secret (whsec_…), under Reveal on the endpoint in Stripe’s dashboard. Choose Stripe and paste it. While Stripe rolls a secret it can sign with both, and rotating here keeps the old one verifying through the overlap.

GitHub

When you add the webhook in GitHub, set Content type to application/json and set a Secret: a long random string. Give Hookie the same value under GitHub. GitHub’s Recent Deliveries shows Hookie’s 401 body when a delivery is refused.

Shopify

Shopify signs with your app’s client secret, or, for webhooks created under Notifications, the signing secret shown on that page. Choose Shopify and paste it. Shopify signs no timestamp, so there is no tolerance to set. When you rotate the app’s client secret, rotate here too.

Slack

Use the Signing Secret on your Slack app’s Basic Information page. An endpoint that also answers Slack’s url_verification handshake keeps answering it, since the handshake is handled before the signature check.

Standard Webhooks and Svix

For any sender that follows Standard Webhooks, including services built on Svix and another Hookie workspace’s destinations, choose Standard Webhooks (Svix and others) and paste the whsec_… secret. For any other sender that signs the body with a shared secret, choose Custom HMAC and set the HMAC options.