Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →If webhook verification started failing after you added JSON or form-body parsing, the first suspect is that your verifier no longer sees the exact request bytes the provider signed. Preserve the raw body for the webhook route, then check the provider’s specific signature header, algorithm, secret, and—only when relevant—timestamp rules. Stripe, GitHub, Slack, and SendGrid do not use interchangeable signing schemes.
Why parsing breaks signature verification
A webhook signature authenticates a specific input, not merely the data represented by that input. A JSON parser can turn incoming bytes into an object; serializing that object later may change whitespace, escaping, key order, or character encoding. The reconstructed JSON can mean the same thing to your application while having different bytes from the original payload. A verifier given those altered bytes calculates a different signature.
As an Amazon Associate I earn from qualifying purchases.
Stripe says verification requires the raw, unmodified incoming body. Slack likewise directs developers to read the raw request body before JSON or other deserialization, and SendGrid’s Node.js guide requires a raw Buffer or string. See Stripe’s troubleshooting guidance, Slack’s request-verification guide, and SendGrid’s Node.js guide.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitches“Raw body” means the representation required by that provider’s verification procedure, preserved before application middleware transforms or consumes it. It does not mean converting a parsed object back into JSON and calling the result raw.
#1 Best Overall
Debug in this order
- Identify the provider and exact failure. Separate a digest mismatch from an error indicating that a signed timestamp is outside its allowed tolerance. For Stripe, the error “no signatures found matching the expected signature for payload” can point to a modified body or the wrong endpoint signing secret, among other input mismatches. Stripe’s troubleshooting page discusses these causes.
- Find what reads or transforms the body first. Follow middleware and route registration order. Look for global JSON and URL-encoded parsers, multipart handlers, framework adapters, custom parsing, decompression, or text decoding that runs before verification. Confirm whether the verifier receives original bytes, not a parsed object or a serialized reconstruction.
- Preserve raw input on the webhook route. Configure the route to receive the raw representation expected by the provider’s SDK before any parser consumes it, or exempt the route from the global parser. In its Express example, SendGrid excludes its webhook path from JSON parsing and applies raw parsing to that route. Framework and hosting-adapter details differ, so use the raw-body mechanism supported by your stack and SDK. See SendGrid’s route-specific example.
- Compare body and headers across boundaries. Temporarily compare the body’s byte length and a digest computed locally at the earliest application boundary and immediately before verification. Do not log signing secrets or full sensitive payloads. Check whether a proxy, load balancer, serverless adapter, decompression layer, or character-decoding step changes the body or signature headers. GitHub’s troubleshooting guidance warns against payload or header changes between sender and verifier.
- Confirm the exact provider inputs. Use the provider’s expected header, algorithm, secret, and any required encoding. Check that the secret belongs to the endpoint or environment that actually sent the request. Do not assume that a valid secret for a different endpoint, test setup, or integration will verify this delivery.
- Investigate time only for timestamp-related errors. Check server clock accuracy and whether verification is delayed. Do not treat a timestamp failure as proof that the payload was parsed incorrectly, or apply one provider’s freshness window to another.
- Verify before processing event data. Reject invalid signatures before triggering business actions. Use the provider’s recommended constant-time comparison mechanism rather than a direct string comparison. See GitHub’s validation guidance and Slack’s verification guide.
Provider-specific checks
| Provider | What to verify | Distinctive checks |
|---|---|---|
| Stripe | Use the raw, unmodified request body and the signing secret for the receiving endpoint. | Check that the endpoint secret is the right one for the delivery environment; Stripe’s support guidance also distinguishes a Stripe CLI listener secret. For timestamp-tolerance errors, check server time and verify promptly. Stripe troubleshooting. |
| GitHub | Prefer X-Hub-Signature-256 with HMAC-SHA256 and the configured webhook secret. |
The signature is a hex HMAC digest prefixed with sha256=; validate it against the payload using a constant-time comparison. Check UTF-8 handling where the server specifies character encoding, and ensure intermediaries leave payload and headers unchanged. Troubleshooting and validation. |
| Slack | Use X-Slack-Signature and the raw body. |
Slack’s HMAC-SHA256 input is a versioned base string containing the version, timestamp, and raw body. Its guide demonstrates rejecting timestamps more than five minutes from local time; that is Slack’s documented example, not a universal webhook rule. Use a constant-time comparison. Slack request verification. |
| Twilio SendGrid (Node.js guide) | Verify the raw body as a Buffer or string. | When using express.json() or bodyParser.json(), exclude the webhook route from that parser and apply raw parsing to it, as shown in the guide. SendGrid Node.js guide. |
Common fixes that do not fix the cause
- Parsing, then stringifying again: equivalent JSON data is not necessarily equivalent signed input.
- Changing the secret before checking the body: a wrong secret can cause a mismatch, but changing secrets will not repair bytes altered by middleware.
- Using a different provider’s header or recipe: the header names, signed inputs, timestamp rules, and secret scopes vary.
- Logging sensitive data to diagnose the issue: compare byte counts or temporary digests instead; never expose signing secrets.
- Delaying verification while doing business work: verify promptly and before processing event data. GitHub says a delivery should receive a 2xx response within 10 seconds or it treats the delivery as failed; that response timing is not a remedy for a signature mismatch. GitHub troubleshooting.
After the fix
Retest through the same route and hosting path that receives real deliveries. Confirm that verification succeeds with the untouched request representation, fails if the body is deliberately altered, and runs before event processing. Keep the webhook route’s raw-body handling isolated from ordinary routes that need parsed JSON, and preserve the provider’s own verification library and rules.
Quick Recap
Rank #4
Rank #2
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




