All Glossary Terms
HTTP & Concept

What is a http status code?

An HTTP status code is the 3-digit response code your handler returns — providers expect 2xx for success and retry on most non-2xx. Standard responses by scenario: signature verified + event queued → 200; signature failed → 401; malformed payload → 400 (retry won't help); duplicate event ID already processed → 200 (duplicates aren't errors); internal error → 500 (retry is correct). Two anti-patterns: returning 200 with an error in the body (the source sees "delivered" and the event is lost), and returning 5xx forever for a permanent bug (events accumulate retries for days). Latency matters too — ack within seconds, do work asynchronously.

Every HTTP response carries a status code. For webhook handlers, the status code your handler returns is the *only* signal back to the source about whether the event was successfully received. Get it right or events get retried unnecessarily, dropped silently, or treated as your endpoint being broken.

The provider's interpretation of your status code is approximately:

- 2xx (200-299): success. Source marks the delivery delivered. No retry. The standard response is plain 200 OK. Body content is usually ignored, but some providers display it in their dashboard for debugging — keep it short, no secrets. - 3xx (300-399): redirect. Most providers do *not* follow redirects on webhook deliveries. Don't redirect; serve directly. - 4xx (400-499): client error. Provider behavior varies. Some treat 4xx as terminal (don't retry — your endpoint rejected the request and won't accept a retry). Some retry 4xx anyway. Don't return 4xx for transient issues; only for "this request will never succeed" (signature failure → 401, malformed payload → 400). - 5xx (500-599): server error. Universally retried. The expected response when your handler is broken or your downstream services are down.

What your handler should return, by scenario:

- Signature verification passed, event queued for processing → 200. - Signature verification failed → 401. (Some teams use 400; either is fine, but 401 is more semantic.) - Signature passed but the event is malformed JSON / missing required fields → 400. Retry won't help; the body is bad. - Signature passed, body is fine, but you've already processed this event ID → 200. Don't 4xx; duplicates aren't errors, they're expected. - Internal error before signature check (DB unavailable, can't read secret) → 500. Source will retry; this is the right behavior. - Internal error after signature check (queue is down, DB write failed) → 500. Retry is correct; you didn't durably accept the event.

Two anti-patterns:

- Returning 200 with an error in the body. "Status 200, body {error: 'failed'}" tells the source the delivery succeeded. The event is now lost. Always use the status code; the body is for human debugging, not machine logic. - Returning 5xx forever. If a permanent bug means a class of events never succeeds, those events accumulate retries for days, blowing up source-side dashboards and your own logs. Either fix the bug or 4xx the events to mark them terminal.

Latency matters too. A 200 returned in 10 seconds may already be too late — the source timed out at 3 seconds, considered the delivery failed, and started retrying. Always ack fast; do work asynchronously.

See HTTP Status Code in real traffic

WebhookWhisper captures every webhook with full headers, body, signature, and timing — so concepts like http status code stop being abstract and become something you can inspect.

Start Free