Common Webhook HTTP Errors and How to Fix Them
Diagnose webhook 400, 401, 404, 413, 429, 500, 502, and timeout responses with concrete checks for handlers and reverse proxies.
The HTTP status returned by a webhook endpoint is the fastest clue about where delivery failed. It is not a complete diagnosis, but it narrows the search to configuration, authentication, payload handling, rate limits, or server availability.
First capture the exact request in a webhook inspector, then replay it against your endpoint with cURL. This separates provider behavior from your application behavior.
400 Bad Request
A 400 usually means the endpoint received the request but could not parse or validate it.
Check:
- malformed JSON or unexpected character encoding;
- a body parser that expects JSON while the provider sends form data;
- missing required headers or fields;
- timestamp validation failures;
- framework validation that rejects unknown fields.
Replay the same content type and raw body:
curl -i -X POST https://api.example.com/webhooks \
-H 'content-type: application/json' \
--data-binary @captured-body.json
Use --data-binary when exact bytes matter. Plain --data can modify line endings or apply form semantics.
401 Unauthorized or 403 Forbidden
These statuses indicate authentication or authorization failure. For webhooks, that usually means signature verification failed or generic application middleware blocked the request.
Verify:
- the signing secret belongs to this exact endpoint and environment;
- you verify the unmodified raw body;
- the signature header name matches the provider documentation;
- the server clock is synchronized;
- the route is excluded from browser-oriented CSRF and login middleware.
A webhook should not rely on a session cookie. Authenticate the sender with an HMAC or asymmetric signature provided for machine-to-machine delivery.
404 Not Found
A 404 means the request reached a server, but the final route did not match.
Common causes:
- the configured path is missing an API prefix;
- the request reached the wrong virtual host;
- a deployment changed the route;
- a reverse proxy stripped or duplicated a prefix;
- a trailing-slash policy redirected to a route that does not accept the method.
Inspect the effective URL:
curl -i -X POST https://api.example.com/webhooks/provider
Avoid relying on redirects. Configure the provider with the final HTTPS endpoint.
405 Method Not Allowed
The route exists but does not accept the provider's method. Most event webhooks use POST, while verification challenges may use GET.
Confirm which methods the provider sends and define handlers for each required flow. Return an Allow header when possible so the failure is self-explanatory.
413 Payload Too Large
A proxy or framework rejected the request before or during body parsing.
Check limits at every layer:
- CDN or load balancer;
- nginx or Apache;
- framework body parser;
- serverless platform;
- application-specific validation.
Set a deliberate upper bound rather than removing all limits. Webhook endpoints are public attack surfaces. If legitimate events exceed the limit, increase it consistently across layers and stream large bodies where practical.
415 Unsupported Media Type
Your endpoint does not support the request's Content-Type. Providers may send JSON, URL-encoded forms, plain text, XML, or multipart payloads.
Capture the real header and configure the matching parser. Do not force every body through JSON.parse.
429 Too Many Requests
The endpoint or an upstream service is rate-limiting delivery. Providers often retry 429 responses with backoff, which can increase the backlog.
Return a Retry-After header when your rate limit is temporary:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
For bursty webhook traffic, acknowledge validated events into a queue and rate-limit downstream processing instead of inbound delivery.
500 Internal Server Error
Your application threw an error or explicitly returned 500. Correlate the provider's event ID with application logs, but avoid logging sensitive payloads.
Typical causes include:
- unhandled payload variants;
- database connection failures;
- assuming optional fields always exist;
- performing slow third-party requests inline;
- duplicate events violating a unique constraint without graceful handling.
Return 5xx only when retrying may succeed. A permanently invalid payload should receive a suitable 4xx; otherwise providers may retry it for hours.
502 or 503 from a proxy
The reverse proxy or load balancer could not reach a healthy application instance.
Check:
systemctl status your-webhook-service
curl -i http://127.0.0.1:3000/health
ss -lntp
Look for process crashes, wrong upstream ports, deploy restarts, exhausted connection pools, and health checks that do not represent actual readiness.
Timeouts with no status
The provider connected but did not receive a complete response in time. Move slow work out of the request path and acknowledge after the event is durably queued.
Measure separately:
- time to accept and verify the HTTP request;
- time to enqueue it;
- time for background processing;
- time for downstream side effects.
The webhook response should depend only on the first two.
A repeatable debugging loop
For any status:
- Capture the provider's exact request.
- Reproduce it with cURL.
- Test the public proxy and local application separately.
- Correlate by event ID.
- fix one layer and replay the same request.
Keeping the input constant turns an intermittent webhook report into a normal HTTP debugging task.