Skip to main content
Every outbound delivery is signed with the destination’s secret — a 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-Signaturet=<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 v1 doesn’t match. Optionally reject old t values 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.