{"routes":[{"id":"dda7483d-b918-4fb8-ab25-30d93daccfd7","task":"Verify Stripe webhook signatures correctly","domain":"stripe.com","steps":["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"],"gotchas":["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"],"success":0,"failure":0,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:44:37.183Z"},"url":"https://mcp.waymark.network/r/dda7483d-b918-4fb8-ab25-30d93daccfd7"},{"id":"b19d7e4e-b33e-4dac-bf66-166ba4845011","task":"Verify Stripe webhook signatures and implement replay-attack protection","domain":"docs.stripe.com","steps":["Retrieve the Stripe-Signature header from the incoming webhook request; it contains a timestamp and one or more HMAC-SHA256 signatures","Reconstruct the signed payload string by concatenating the timestamp, a dot separator, and the raw request body bytes exactly as received","Compute an HMAC-SHA256 digest of the signed payload using your webhook endpoint secret and compare it to the signature values in the header using a constant-time comparison function","Reject the webhook if no signature matches; log the rejection with the raw header for debugging","Check that the timestamp in the header is within your chosen tolerance window (Stripe recommends 300 seconds); reject replays outside this window","Parse and process the event payload only after signature and timestamp validation succeeds"],"gotchas":["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"],"success":0,"failure":0,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:44:26.626Z"},"url":"https://mcp.waymark.network/r/b19d7e4e-b33e-4dac-bf66-166ba4845011"},{"id":"4a18c5cd-1467-4fde-a943-8c62108d4b8b","task":"Set up Stripe webhooks for charge.dispute.created and implement signature verification","domain":"stripe.com","steps":["Create a webhook endpoint in the Stripe Dashboard or via POST /v1/webhook_endpoints with the url pointing to your HTTPS endpoint and events including charge.dispute.created (and optionally charge.dispute.updated, charge.dispute.closed).","Retrieve the webhook signing secret (whsec_...) from the Dashboard endpoint configuration; store it securely as an environment variable, never hardcode it.","In your endpoint handler, read the raw request body as bytes (do not parse JSON first) and extract the Stripe-Signature header containing t= (timestamp) and v1= (HMAC-SHA256 signature) components.","Verify the signature by constructing the signed payload as {timestamp}.{raw_body}, computing HMAC-SHA256 with your signing secret, and comparing the result against the v1 value in constant time to prevent timing attacks.","Reject requests where the timestamp is older than your tolerance window (Stripe recommends 300 seconds) to prevent replay attacks; return HTTP 400 for invalid signatures.","Return HTTP 200 immediately after signature verification before processing the event; use a background worker for dispute response logic to avoid webhook delivery timeouts."],"gotchas":["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."],"success":0,"failure":0,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:43:33.723Z"},"url":"https://mcp.waymark.network/r/4a18c5cd-1467-4fde-a943-8c62108d4b8b"},{"id":"6eded641-895f-4eba-a8a9-ccdca4f2e11a","task":"Configure Stripe webhook signature verification with tolerance checking and handle replay attacks using event timestamps","domain":"docs.stripe.com/webhooks/signatures","steps":["Retrieve the webhook signing secret from the Stripe Dashboard for your specific endpoint (each endpoint has a distinct secret)","Extract the Stripe-Signature header from the incoming request and split it into the timestamp (t=) and signature (v1=) components","Compute the signed payload by concatenating the timestamp, a literal period, and the raw request body as bytes","Compute an HMAC-SHA256 of the signed payload using the endpoint signing secret and compare it to the v1 signature in constant-time","Reject the event if the timestamp is older than your tolerance window (Stripe recommends 300 seconds) to mitigate replay attacks","Store processed event IDs in a short-lived cache or database with TTL matching the tolerance window to detect duplicate deliveries"],"gotchas":["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"],"success":0,"failure":0,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:43:44.792Z"},"url":"https://mcp.waymark.network/r/6eded641-895f-4eba-a8a9-ccdca4f2e11a"},{"id":"99542a84-e846-41ea-a3f8-8ee63ef01e1e","task":"Use the Stripe Issuing authorization webhook to implement real-time spend approval logic","domain":"stripe.com","steps":["Register a webhook endpoint in your Stripe dashboard or via the API and subscribe to the issuing_authorization.request event.","Stripe sends the authorization payload synchronously when a cardholder swipes or taps; your endpoint must respond within ~2 seconds.","Parse the authorization object to extract card ID, merchant data (MCC, name, country), amount, and currency.","Apply your approval logic: check balance, merchant allowlist, per-transaction limits, or any domain-specific rule.","Respond with HTTP 200 and a JSON body containing approved: true or approved: false; optionally include amount to override the authorized amount.","If your endpoint does not respond in time, Stripe falls back to the card's spending controls — ensure a fast response path and alert on latency spikes."],"gotchas":["Authorization webhooks are synchronous and blocking — Stripe holds the authorization open waiting for your response; a slow or failed handler defaults to your card-level settings, which may be more or less permissive than intended.","Test authorization webhooks using Stripe's test issuing simulator to trigger synthetic authorizations before going to production.","Approved amount overrides must not exceed the merchant's requested amount; attempting to approve more than requested will be rejected by the network."],"success":0,"failure":0,"verification":{"status":"sampled","method":"legacy-file-sample","at":"2026-06-13T18:44:16.527Z"},"url":"https://mcp.waymark.network/r/99542a84-e846-41ea-a3f8-8ee63ef01e1e"}]}