What to send
When a Stripe webhook breaks, the customer has paid but your app does not know it: orders stay "pending", subscriptions never activate or never cancel, and access is wrong. To scope the fix, send:
- The site or app URL, the stack (Laravel, plain PHP, WooCommerce, Next.js, Node or other) and the webhook endpoint path.
- When it started and what changed just before: a deploy, a Stripe API version upgrade, a new endpoint, a domain or SSL change, a move behind Cloudflare or a new host.
- A copy of one failed event from Developers → Webhooks → your endpoint → Event deliveries in the Stripe Dashboard, showing the HTTP status and response body.
- The matching lines from your server or application log for the same time.
- Whether the problem is in test mode, live mode or both.
Send your Stripe webhook problem for a written scope and reply within 24 hours. Never paste your secret key (sk_live_...) or webhook signing secret (whsec_...) into the public inquiry form.
Common causes of Stripe webhooks not working
- Signature verification fails:
No signatures found matching the expected signature for payload. The handler verifies a parsed or re-encoded body instead of the raw request body, or uses the signing secret from a different endpoint or mode. Each endpoint, and the Stripe CLI, has its ownwhsec_secret. - Test and live mode mixed up: the endpoint is registered in test mode while the site runs live keys, or the reverse, so events never reach the endpoint you are watching.
- The endpoint returns an error before your code runs: a 301/302 redirect (HTTP to HTTPS, or
wwwto the bare domain), a 403 from a firewall, bot protection or security plugin, a 404 after a route change, or a 419 in Laravel because the webhook route is not excluded from CSRF verification. Stripe does not follow redirects for webhook deliveries. - Timeouts: the handler does slow work (emails, PDFs, external API calls) before responding, Stripe times out and retries, and the same event is processed twice or not at all.
- Events not subscribed or not handled: the endpoint listens for
checkout.session.completedbut notinvoice.paid,invoice.payment_failedorcustomer.subscription.updated, so renewals, upgrades and cancellations never reach the database. - Lookup mismatch: the handler looks up the user by an ID that was never stored (
customer,subscriptionorclient_reference_id), so the event gets a 200 response but updates nothing. - API version drift: the endpoint's API version differs from what the code or library expects, so a field the handler reads has moved or changed shape.
- Duplicate and out-of-order events: Stripe can deliver the same event more than once and not in order. Without idempotent processing, orders are fulfilled twice or an old event overwrites a newer state.
Safe checks you can run yourself
- Read the event deliveries log. In the Stripe Dashboard, open the endpoint and check the HTTP status of recent attempts. A 3xx, 4xx or 5xx status points at the server; a 200 with no change points at the handler logic.
- Confirm mode and URL. Make sure the endpoint is registered in the same mode as your API keys and that the URL is the final HTTPS address with no redirect.
- Check the signing secret. Compare the
whsec_value in your environment with the one shown on that specific endpoint. After changing it, clear any cached config (for examplephp artisan config:clearin Laravel). - Resend one event. Use Resend on a failed event in the Dashboard, or
stripe events resend evt_...with the Stripe CLI, and watch your log at the same time. - Test locally with the CLI.
stripe listen --forward-to localhost:8000/your-webhook-pathandstripe trigger checkout.session.completedshow whether the handler works before the network is involved.
If these do not find it, stop changing the live endpoint and send the details; editing secrets and routes at random can make failed events harder to replay.
Price, delivery and guarantee
Affordable and low-cost does not mean open-ended: this fix is a $99 fixed price, agreed in writing before work starts, delivered within 48 hours of receiving the required access.
- Fully written. No calls and no project managers.
- Fixed and tested in Stripe test mode on a staging copy first, then released to production after you approve it.
- You receive written proof: the root cause, what changed, the successful test deliveries and a rollback note.
- Money-back guarantee if the agreed root cause cannot be resolved.
- The delivery note lists which failed live events to resend from the Dashboard so missed orders or subscriptions catch up.
A new payment integration, a different checkout flow or a billing rebuild is outside the fixed price and receives a separate written quote. See API integration and webhook development for that work, or PHP and Laravel development if the handler lives in a PHP app.
FAQ
How much does it cost to fix a Stripe webhook that is not working?
The fix is $99 fixed price for the confirmed issue, including root-cause diagnosis, a test-mode check on staging, the fix, written proof and a rollback note. Typical agency hourly rates are higher and open-ended, while very low marketplace gig prices rarely include root-cause diagnosis, staging tests or a guarantee.
What is the best way to fix a failing Stripe webhook?
Start from the Stripe event deliveries log, not the code: the HTTP status tells you whether the request reached your handler. Fix the first real failure, verify signatures on the raw body, respond quickly and do slow work afterwards, make processing idempotent, then resend a failed event to prove it. When choosing a payment bug-fix service, look for a fixed price, staging first, root-cause explanation, written proof and a guarantee.
Do you need my live Stripe secret key?
Usually not. Most fixes are done with test-mode keys on staging. If live configuration must change, you make the change from written steps, or grant a restricted, revocable key that you can roll afterwards.
Will customers who already paid be updated too?
Stripe retries failed events for a limited period, and events can be resent from the Dashboard once the endpoint works, so missed orders or subscriptions can catch up. Anything that cannot be replayed is listed in the delivery note for manual review.
Which platforms does this cover?
Custom PHP and Laravel, WooCommerce with a Stripe plugin, and Next.js or Node handlers. Portfolio work includes webhook-driven Stripe subscription fulfillment with idempotent processing on a Next.js app and Stripe payment work on a Laravel platform.
Can this be done without calls?
Yes. Everything is in writing: scope, questions, approval and delivery.
Next step
Send one failed event and the log lines and get a written fixed-price scope within 24 hours. For the signature error specifically, read how to fix "No signatures found matching the expected signature".