Read the header
Each destination gets awhsec_... secret when you create it. Courier signs every request with HMAC-SHA256 in a courier-signature header:
Compare the signature
Split the header on, and = to read t, a millisecond timestamp, and signature. Compute HMAC_SHA256(secret, "<t>.<raw_body>") and compare it to signature in constant time:
Limits & behavior
- Verify against the raw body. Re-serializing the JSON changes the bytes, so the signature won’t match.
- Use a constant-time comparison. A plain string comparison leaks timing information.
FAQ
How do I know a request really came from Courier?
How do I know a request really came from Courier?
Verify the
courier-signature header. Compute HMAC_SHA256(secret, "<t>.<raw_body>") with your webhook’s whsec_ secret and compare it to the header’s signature. Reject anything that does not match.Why does my signature check keep failing?
Why does my signature check keep failing?
Almost always because the body was parsed and re-serialized before hashing. Hash the raw bytes of the request instead.