Stripe sends payment events to a preview, not your live app

Payments go through, but paying customers do not get access, and your live app never sees a Stripe event.

Why it happens

The webhook endpoint in Stripe still points at the address you used while building: a preview deploy, a tunnel from your own computer, or an old Supabase project. Stripe delivers every event there, so the live app never hears about a payment. The preview worked, so the setup looked finished.

How to tell

  • Under Stripe › Developers › Webhooks, the endpoint's address is a preview (such as my-app-git-feature-acme.vercel.app or id-preview--….lovable.app) or a tunnel (ngrok).
  • No endpoint points at your live domain or your live Supabase project.
  • The payments are in Stripe; the matching rows or emails in your app are not.

The fix

  1. In Stripe › Developers › Webhooks, add an endpoint on your live address (for example https://yourdomain.com/api/stripe/webhook, or your live Supabase function's URL) and give it the same events as the old one.
  2. Put the new endpoint's signing secret in your live host's production environment, then redeploy.
  3. Send a test event from Stripe and confirm your live app answers 200.
  4. Replay the events from the gap to the new endpoint (Stripe CLI: stripe events resend <event id> --webhook-endpoint <new endpoint id>), so customers who already paid get what they paid for.
  5. Delete the old endpoint once nothing uses it, after checking it is not another app's.

Where to look

The prompt for your builder

Paste this into Lovable, Bolt, Cursor, Claude Code or whatever built the app. Replace anything in capitals. It never asks you to paste a secret into a chat; keys go into your host’s environment, by you.

Prompt for your builder
My Stripe webhook points at a preview address instead of my live app. Tell me the exact URL my live webhook route is served at in production and which Stripe events it handles. Then check that the route reads its signing secret from STRIPE_WEBHOOK_SECRET — I will set that value on my host myself, not here — and that it answers 200 only after its work is saved.

How Keelnest catches it

Revenue Guard reads your Stripe webhook endpoints every hour and opens an incident when every endpoint points at a preview, a tunnel or a staging address, so no event reaches your live app.

Know the moment this happens.

Keelnest watches your production app every five minutes and tells you in plain English what broke — with the fix. Free for your first app.

Related