Generate Webhook Signatures

Paste the exact webhook body and endpoint secret, pick a provider, and produce the signed payload, HMAC, headers, or replay cURL command locally.

Try:
Signature result

About this tool

Webhook Signature Generator builds the HMAC headers that webhook providers send with a delivery. Paste the exact raw body, the endpoint's signing secret, and a fixed timestamp when the provider uses one; the tool returns the signed byte string, the encoded HMAC, finished header lines, and an optional replay curl command.

A worked Stripe example:

  1. Payload: {"id":"evt_test","type":"payment_intent.succeeded"}
  2. Secret: whsec_test_secret
  3. Provider: stripe
  4. Timestamp: 1700000000
  5. Output: headers

The primary result is a Stripe-Signature header in the t=1700000000,v1=<hex hmac> format. Switch the provider to GitHub, Slack, Shopify, Standard Webhooks, Svix, Square, Twilio, or Paddle to use that provider's canonical string-to-sign and header layout.

Use custom when a webhook source only says "HMAC this string". The custom mode supports {payload}, {timestamp}, {id}, and {url} placeholders, selectable HMAC algorithms, hex/base64 encodings, and your own header name/prefix.

Limits and edge cases:

FAQ

Why does changing JSON formatting change the signature?

Webhook providers sign the raw request body bytes, not the parsed JSON object. A pretty-printed JSON document, compact JSON document, or reordered object can all represent the same data while producing different bytes and therefore different HMACs. Paste the body exactly as your receiver sees it.

What timestamp should I use?

Use the timestamp from a real delivery when you want to reproduce or debug a mismatch. Leave it blank when generating a fresh replay header for providers such as Stripe or Slack; the page and CLI fill the current Unix seconds. Receivers usually reject old timestamps, so a historical signature may need a test-mode bypass on your endpoint.

Why are Standard Webhooks and Svix secrets decoded but Stripe secrets are not?

Standard Webhooks and Svix define whsec_ as a prefix before base64 key material, so auto strips the prefix and decodes the rest. Stripe's whsec_... value is used as literal text for the HMAC key. Mixing those conventions is a common source of signatures that look valid but never verify.

Can this verify incoming webhook requests?

No. It is a generator for replay and endpoint tests. To verify a request, compute the same signature with the raw body and compare it to the incoming header using constant-time comparison in your server code, along with provider-specific timestamp and replay checks.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool webhook-signature-generator '{"id":"evt_test","type":"payment_intent.succeeded"}' 'secret=whsec_test_secret'

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/webhook-signature-generator/?payload=%7B%22id%22%3A%22evt_test%22%2C%22type%22%3A%22payment_intent.succeeded%22%7D&secret=whsec_test_secret&provider=stripe&timestamp=1700000000&message_id=msg_2KWPBgLlAfxdpx2AI54pPJ85f4W&url=https%3A%2F%2Fexample.com%2Fwebhook&algorithm=sha256&encoding=hex&secret_encoding=auto&template=%7Btimestamp%7D.%7Bpayload%7D&header_name=X-Signature&signature_prefix=sha256%3D&output=all

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.