Webhook Payload Builder
Build a webhook payload, sign it with a real HMAC-SHA256 in four common schemes, and verify a signature your endpoint already rejected.
HMAC-SHA256 computed in your browser over the exact bytes shown below.
- Header
- Stripe-Signature
- Body bytes
- 494
- Scheme
- stripe
- Signed timestamp
- 1785312000
- That timestamp reads as
- 2026-07-29T08:00:00.000Z
- The signature covers these exact bytes, indentation included. Real senders transmit compact JSON — if your receiver re-serialises the body before verifying, it will compute a different signature and this is where that bug lives.
Webhook signature verification fails in the same three ways for everyone, and none of them are cryptography. This page exists to tell those three apart, which is why it verifies as well as signs: paste the header your endpoint rejected, and if it matches what this page computes, the HMAC is fine and the bug is elsewhere.
The bug that is always the bug
A signature covers bytes, and a JSON body parsed and re-serialised is a different sequence of bytes with the same meaning — keys reordered, whitespace gone, a float rendered differently. Every framework that hands you a parsed body has already destroyed the thing you need to verify. The fix is to read the raw body before any JSON middleware touches it, and the toggle above exists so you can watch the signature change when the formatting does.
Why the timestamp is signed too
A signature over the body alone is replayable forever: anyone who captures one valid delivery can send it again next year and it will verify. Signing the timestamp alongside the body, and rejecting anything outside a few minutes, is what closes that — which is why the Stripe and Standard Webhooks schemes concatenate the timestamp into the signed string rather than merely sending it. If you are designing a sender, do the same; if you are receiving, check the window as well as the digest.
Use a test secret
Everything here runs in your browser and nothing is transmitted, which is true and is not a reason to paste a live signing secret into a web page. Use the one from your test environment. If you are debugging a production failure, rotate afterwards — the cost is a few minutes and the alternative is a secret whose history now includes a text field.