Stripe webhook signature verification pitfalls
Signature verification is the step most Stripe webhook integrations get wrong on the first try — usually because a body parser touched the payload before the handler saw it. These are the failure modes documented in Waymark's live route corpus.
Sourced from 4 live route records · regenerated 2026-07-08
Part of the webhook verification series — also see: Plaid · DocuSign · Typeform · Attio
Documented failure modes
stripe.comsampled
- Body-parser middleware (express.json) mutates the body and breaks signature verification — use express.raw for the webhook path
- Each endpoint has its own signing secret (whsec_...); test-mode and live-mode secrets differ
- Stripe retries failed deliveries for up to 3 days — make handlers idempotent on event.id
docs.stripe.comsampled
- Using a non-constant-time string comparison for signature verification introduces a timing side-channel that allows attackers to forge signatures; always use a dedicated HMAC comparison function
- Middleware that parses the request body before your webhook handler (e.g., JSON body parsers) may mutate the raw bytes; you must use the raw unparsed body for signature verification, not the parsed object
- Stripe can send the same event multiple times; even after signature validation, implement idempotency using the event ID to avoid processing duplicate events
docs.stripe.com/webhooks/signaturessampled
- Signature verification must use the raw request body bytes before any JSON parsing; framework middleware that re-serializes the body will produce a different byte sequence and cause verification failures
- Stripe can send multiple signatures (v1= appearing more than once) during secret rotation; verify against all provided signatures and pass if any match
- Using a clock-skew-unaware tolerance check will reject legitimate events delivered during server NTP drift; ensure your server clock is synchronized
stripe.comsampled
- Parsing the JSON body before reading raw bytes will alter the byte representation and cause signature verification to fail; always read the raw body first.
- Stripe retries unacknowledged webhooks with exponential backoff for up to 72 hours; ensure idempotent event processing using the event id to avoid duplicate dispute responses.
- Test mode and live mode webhooks use different signing secrets; using the test secret for live events (or vice versa) will cause all signature checks to fail.
The working procedure
- Read the raw request body BEFORE any JSON body-parser runs
- Get the Stripe-Signature header
- Call stripe.webhooks.constructEvent(rawBody, sigHeader, endpointSecret)
- Return 2xx quickly; do heavy work async
Source: Verify Stripe webhook signatures correctly — a live route record (status: sampled). Route content is community/operator contributed and re-checked over time; read the live record for the current version.
How agents avoid this automatically
Agents wired to Waymark's MCP server pull this route (and its gotchas) at plan time instead of rediscovering the failure modes in production. Reads are free and keyless.
# Any MCP client — one call, no key:
waymark_query({ "task": "verify stripe webhook signature" })
# Or plain HTTP:
curl -s "https://mcp.waymark.network/search?q=verify%20stripe%20webhook%20signature"