Webhook delivery failed (endpoint returned non-2xx / timed out)
The provider tried to send a webhook to your endpoint but didn’t get a timely 2xx response, so it marks the delivery failed and retries — eventually disabling the endpoint.
Meaning
Webhook senders (Stripe, GitHub, Razorpay, Shopify, Twilio) expect a 2xx within a few seconds. Anything else — 3xx redirect, 4xx, 5xx, timeout, TLS error, DNS failure — counts as a failed delivery. After repeated failures many providers disable the endpoint and email you.
Common traps: the URL redirects (http→https, trailing slash, www), a login/CSRF middleware blocks the POST, or the handler does slow work before replying.
Common causes
- Endpoint returns a redirect (301/302) instead of 2xx
- CSRF, auth or firewall/WAF blocks the provider’s POST
- Handler does slow work synchronously and times out
- Signature check fails so the app returns 400/401
- Endpoint unreachable (localhost URL, expired TLS, DNS)
⚡ Quick fix
- Return 200 immediately, then process the event in a background job
- Use the exact final URL (https, correct host, no redirect)
- Exempt the webhook route from CSRF/login middleware
- Check the provider’s delivery log for the response code it received
Detailed fix by platform
Express
- bash
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => { const event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], secret); queue.add(event); // do the work later res.sendStatus(200); // acknowledge fast });
Laravel
- bash
// app/Http/Middleware/VerifyCsrfToken.php protected $except = ['webhooks/*'];
How to diagnose
- Delivery log — Response code/time the provider recorded
- Redirects — curl -I the URL — any 3xx?
- Middleware — CSRF/auth on the route?
- Duration — How long the handler takes
🧠 Still stuck? Analyze your error
Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.
Report a correction or suggest an improvement
Last updated 7 Oct 2026