whsec_-prefixed value Hookie generates when you create the destination. Verify it before trusting the payload.
You never have to write it down. The secret is encrypted at rest and masked in the console, and the destination’s Reveal button fetches it on demand — an owner or admin only, and every reveal is written to your audit log. Alongside it, Rotate issues a new one; the very next delivery is signed with it, so update your receiver first or it will reject deliveries until you do.
The headers
Each delivery carries:Hookie-Signature—t=<unix>,v1=<hex>, an HMAC-SHA256 (Stripe-style).Hookie-Event-Id— the event id; dedupe on this, since delivery is at-least-once and unordered.Hookie-Delivery-Id— the specific delivery attempt (useful in logs).
What’s signed
The signed string is<t>.<raw body> — the timestamp, a dot, then the exact request body bytes. Compute HMAC-SHA256(secret, "<t>.<body>") as lowercase hex and compare it to v1 in constant time.
Node.js
Express handler
Notes
- Verify against the raw bytes — re-serializing the JSON will change the signature.
- Reject if the header is missing or
v1doesn’t match. Optionally reject oldtvalues to limit replay. - Always compare with a constant-time function (
crypto.timingSafeEqual). - A destination’s URL is fixed once created — a signature is only meaningful against the URL it was sent to. To move a destination, create the replacement and delete the old one.