00 / guide
Stripe webhook failing with 307 or 308 on Vercel
Event deliveries shows 307 or 308. Stripe doesn't follow redirects. It counts any 3xx as a failure, and the fix is to register the final URL. Stripe: fix HTTP status codes
Free tool: decode any Event deliveries status
01 / find the redirect
1
Ask the URL yourself
Send a POST to the exact URL Stripe has, and look at the status and where it points:
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" \
-X POST https://yourdomain.com/api/stripe/webhookYour handler should answer 400 here (no signature). A 307 or 308 with a new address means something in front of your code is redirecting.
02 / common causes on Vercel
a
www or apex domain redirect
If one of your domains redirects to the other (set in the Domains settings), use the one that serves the page. Vercel: domain redirects
b
vercel.app to your own domain
A rule that sends your-project.vercel.app to your custom domain answers with a redirect. Register the custom domain URL in Stripe. Vercel: choose a canonical production domain
c
Trailing slash
Next.js redirects /api/webhook/ and /api/webhook to one form, based on the trailingSlash setting. Register the form your app serves. Next.js: trailingSlash
d
A redirect rule you added
Redirects in next.config use 308 when permanent and 307 when not. Make sure no rule matches your webhook path. Next.js: redirects
e
Double slash in the URL
Vercel turns // into one slash with a 308 before your code runs. Check the URL in Stripe for a stray extra slash. Vercel: automatic URL normalization
f
Preview deployments with protection
A protected preview may send Stripe to a login page instead of your code. For testing, Vercel's Protection Bypass for Automation can go in the URL as x-vercel-protection-bypass. Treat that URL as a secret. Your live endpoint should point at production, not a preview. Vercel: Protection Bypass for Automation
03 / after the fix
a
Update the endpoint and resend
Set the endpoint URL in Stripe to the final address. Resend a failed event from Event deliveries. A good delivery shows 200. Stripe: debug webhook deliveries
04 / where CheckoutAlarm fits
CheckoutAlarm's page check won't flag this, because your page still loads. With a read-only Stripe key, its Stripe check emails you when events are still not delivered after about 15 minutes.
CheckoutAlarm is new. It only checks sites you prove you own. How to verify
Watch my app free05 / sources
- Stripe: manage webhook endpoints (3xx counts as a failure)
- Vercel: redirects (domain redirects, URL normalization)
- Next.js: redirects (307 and 308)
- Next.js: trailingSlash
- Vercel: Protection Bypass for Automation
Docs checked on Oct 18, 2026.