Webhook signature
A cryptographic header proving a webhook came from the sender you expect and was not altered.
A webhook endpoint is a public URL, so anyone can post to it. Senders therefore sign each payload with a shared secret, usually as an HMAC over the raw body plus a timestamp. The receiver recomputes the signature and rejects anything that does not match. Without verification, an endpoint that creates or updates records will act on whatever a stranger sends it.
Full guide:
How to verify a webhook signature correctly
— Compute an HMAC over the raw request body using the shared secret, compare it to the signature header in constant time, and reject anything that does not match — before the payload is used for anything, including logging it as a legitimate event. Verify against the exact bytes received, because parsing and re-serialising JSON changes them and breaks the comparison.
Key facts
- The signature must be computed over the RAW request body: parsing and re-serialising JSON changes bytes and breaks verification.
- Comparison must be constant-time, because a byte-by-byte comparison that exits early leaks the expected value through timing.
- A timestamp in the signed payload, rejected outside a short window, is what prevents a captured request being replayed later.
- Verification must happen before the payload is trusted for anything, including logging it as a legitimate event.
Frequently asked questions
My signature check fails intermittently. Why?
Usually the body is being read after a middleware has parsed it. Capture the raw bytes before any JSON decoding — key order and whitespace are not preserved through a decode and re-encode.
Is HTTPS enough on its own?
No. HTTPS protects the channel but says nothing about who is posting. Anyone who learns the URL can send a well-formed request over HTTPS; only the signature establishes the sender.
Machine-readable copy of this page:
/glossary/webhook-signature.md