Webhook Signature Verifier API

Check webhook signatures of Stripe, GitHub, Slack, Shopify, PayOS and SePay, or any HMAC: see the expected signature, the signed content and replay windows.

POSThttps://apibox.io.vn/v1/webhook-verify
Security & Crypto▶ Try it online

Signature mismatches are the most common webhook bug: the body was re-serialised, the wrong secret was used, or the timestamp is outside the tolerance. The webhook verify API checks a payload against the signature scheme of the provider and shows the expected value next to the received one. Supported: Stripe (Stripe-Signature t= / v1=, 5-minute tolerance), GitHub (X-Hub-Signature-256), Slack (v0 with X-Slack-Request-Timestamp), Shopify (base64 X-Shopify-Hmac-Sha256), PayOS (HMAC over the sorted data fields, with the exact signed string) and SePay (Authorization: Apikey).

provider=generic covers everything else: HMAC-SHA1/256/512, hex or base64, optional prefix and the header to read. Send the raw body as payload (a string, exactly as received) and either the headers object or the signature.

Use it to debug integrations and in tests; in production verify signatures in your own code. Secrets are used in memory only and never stored or logged.

Parameters

NameInTypeRequiredDefault
providerbodystringnogenericstripe, github, slack, shopify, payos, sepay or generic.
secretbodystringyesSigning secret / API key.
payloadbodystringyesRaw request body, as a string.
headersbodyobjectnoRequest headers (the signature header is read from here).
signaturebodystringnoSignature value, instead of headers.
tolerancebodynumberno300Max age in seconds (Stripe, Slack); 0 = no check.
algorithmbodystringnosha256Generic: sha1, sha256, sha512.
encodingbodystringnohexGeneric: hex or base64.

Example

curl -X POST "https://apibox.io.vn/v1/webhook-verify" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"github","secret":"gh","payload":"{\"id\":\"evt_1\"}","signature":"sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e"}'

Response

{
  "valid": true,
  "provider": "github",
  "expected": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e",
  "received": "sha256=eb445c690721bdf4fa91d361661d981eb0394f3089b9e9dfb96cddaef63da22e",
  "note": "The secret is used in memory only and never stored. …"
}

Use cases

  • Debug “invalid signature” errors with Stripe, PayOS, GitHub
  • Test webhook endpoints in CI
  • Learn how each provider signs webhooks
  • Verify payloads captured with the webhook tester

FAQ

Why does my signature not match?

Usually the body was parsed and re-serialised (different spacing or key order). Signatures cover the exact raw bytes; send payload as the original string.

What is the tolerance?

For Stripe and Slack, signatures older than 300 seconds are rejected to prevent replays. Change it with tolerance=, or use now= to test old events.

Is it safe to send my secret?

It is used only to compute the HMAC and never stored. Prefer test-mode secrets, and rotate any secret that leaks.

Related APIs

Start with 1,000 free requests every month. Get free API key →