Marked as helpful by the asker
If you see nothing in the logs, the function that returns 200 is not the one you think. Two common causes:
- Stripe is still pointing at your old endpoint URL (check Developers → Webhooks, the URL must be the production domain, not a preview URL).
- You have both
pages/api/webhook.tsandapp/api/webhook/route.ts. The old one wins and returns 200 without doing anything.
Also read the body raw before verifying, otherwise the signature check throws:
const body = await req.text()
const event = stripe.webhooks.constructEvent(body, sig, secret)