🌳 API

HTTP Status Code Picker

Not sure which HTTP status code to return? Answer a few questions and this interactive decision tree will find the right one for your API response.

📖 How to Use
1
Read the question and click the answer that matches your scenario
2
Follow the decision path — each answer narrows down the correct status code
3
Get the recommended code with description and when to use it

The On-Call Page That Started With a 200

A payments team once shipped an endpoint that always returned 200 OK, even when a charge failed — the actual outcome was encoded in a JSON field inside the body, {"status": "declined"}. It worked fine for the web frontend, which parsed the body correctly. Then a downstream reconciliation service, written by a different team, was added to watch for failed payment webhooks by checking the HTTP status code alone, on the reasonable assumption that a REST API would use HTTP semantics correctly. Every declined charge was silently counted as successful for weeks, because nothing in the transport layer signaled failure — monitoring dashboards, the load balancer's health metrics, and the reconciliation job all agreed the requests were fine.

The discrepancy was only caught when finance flagged a mismatch between processor settlement reports and the internal ledger. The postmortem's single largest recommendation was blunt: status codes must reflect what actually happened at the HTTP layer, and a JSON body is not a substitute for HTTP semantics that every intermediary in the request path — proxies, gateways, monitoring agents — already knows how to interpret.

Where These Numbers Actually Come From

HTTP status codes are standardized in the IETF's HTTP semantics specification — originally RFC 2616, later split and refined into RFC 7231, and consolidated again into RFC 9110 — which defines the five numeric classes (1xx through 5xx) and the specific meaning of each registered code. Some codes used constantly in modern APIs were added well after the original HTTP/1.1 spec: 429 Too Many Requests arrived in RFC 6585 in 2012 to standardize rate-limit signaling, and 422 Unprocessable Content originated in WebDAV's RFC 4918 before being adopted broadly by REST APIs for semantic validation failures. The IANA maintains the canonical registry of all assigned status codes, and well-behaved HTTP clients, proxies, and caches are expected to fall back to the general behavior of a code's class (2xx succeeded, 4xx client's fault, 5xx server's fault) even for codes they don't specifically recognize — which is exactly why picking a code from the correct class matters more than memorizing every registered number.

Slip-Ups That Keep Showing Up in Code Review

Picking a Code: A Concrete Walkthrough

Say you're building a DELETE /orders/{id} endpoint and need to decide what to return in three scenarios. If the order exists and is deleted successfully, the tree's "success" branch asks whether there's anything to return — since a DELETE typically has no body, the answer lands on 204 No Content, not 200 OK. If the order id doesn't exist at all, the tree's "client error" branch asks what's wrong with the request, and "resource doesn't exist" resolves to 404 Not Found. Now suppose the order exists but is already in a "shipped" state that your business rules forbid deleting — this isn't a missing resource and it isn't malformed input, so neither 404 nor 400 fits; walking the "client error" branch to "validation failed, correct syntax, wrong values" lands on 422 Unprocessable Content, with a response body explaining that shipped orders can't be deleted. Three requests to the same endpoint shape, three different correct codes, decided entirely by what actually happened server-side rather than by habit.

Where Teams Reach for the Tree

Frequently Asked Questions

What is the difference between HTTP 401 and 403?

401 Unauthorized signals that the request lacks valid authentication credentials — the server doesn't know who the caller is. The response should include a WWW-Authenticate header telling the client how to authenticate. 403 Forbidden signals that the server knows who the caller is but refuses to grant access — the resource exists but the caller doesn't have permission to see it. A common security pattern is to return 404 Not Found instead of 403 when you want to conceal the existence of a resource from unauthorized callers.

When should I use 422 instead of 400?

Use 400 Bad Request when the request itself is malformed at the protocol or format level — the JSON body is unparseable, a required header is absent, or the content type is wrong. Use 422 Unprocessable Content when the request is syntactically correct but fails business logic validation — the JSON parses fine but a field value violates a constraint, such as an end date earlier than a start date, a price below zero, or a username that's already taken. This distinction helps API clients distinguish between "fix your serialisation code" (400) and "fix your input data" (422).

What is the difference between 301 and 302 redirects?

301 Moved Permanently tells the client (and search engines) that the resource has permanently moved to the new URL — the client should update any bookmarks and search engines should transfer ranking signals to the new URL. 302 Found (also called "Moved Temporarily") tells the client the resource is temporarily at a different URL but will return to the original — the client should keep using the original URL for future requests. Use 308 Permanent Redirect and 307 Temporary Redirect when you also need to preserve the original HTTP method (POST stays POST) through the redirect.