Free tool

Webhook signature verifier

Paste a webhook's secret, raw body and signature to find out whether they match and why they might not. It runs in your browser with Web Crypto. Nothing you type is sent anywhere, including the secret.

The SendRaven raven holding a wrench and a magnifying glass

Webhook signature verifier

How it works

What a webhook signature proves

Who sent it

Only someone holding the secret can produce the HMAC, so a match means the request came from whoever you shared it with.

What they sent

The HMAC covers the exact bytes of the body. One changed space and it fails, which is what makes it useful and why it fails so often in frameworks.

When they sent it

Schemes that sign a timestamp let you refuse old requests. Without that check, a captured request can be replayed for ever.

SendRaven signs every delivery and retries a failed one on a fixed schedule; the webhooks docs have the event list and the payloads.

FAQ

Questions about webhook signatures

Why does my webhook signature not match?

Nearly always because the body changed before you verified it. Frameworks parse JSON and hand you an object, and stringifying it again changes spacing and key order. Verify against the raw bytes of the request, before any body parser runs.

What is signed in a Stripe-style signature?

The timestamp, a dot and the raw body, as t.body. The header carries both, as t=1767225600,v1=<hex>. Signing the timestamp is what stops an old request being replayed, as long as the receiver refuses one that is too old.

How do I verify a SendRaven webhook?

Each delivery carries an X-CN-Signature header in the form t=<unix>,v1=<hmac>, where the HMAC is SHA-256, hex-encoded, over <t>.<body>, using the endpoint's secret. Pick the SendRaven scheme here to test one.

Is it safe to paste a secret here?

This page computes the signature in your browser with Web Crypto, and it makes no request with what you type. Even so, a rehearsal with a test secret is good practice, and rotate any production secret you have pasted somewhere you did not intend to.

Should I compare signatures with ==?

No. Use a constant-time comparison, such as crypto.timingSafeEqual in Node or hmac.compare_digest in Python, so that the time taken does not reveal how much of a forged signature was right.

Next step

Signed events for every send, bounce and reply

Delivery events and received mail reach your endpoint signed, with retries, over one API.