Every HTTP status code worth knowing, from 200 and 301 to 429 and 503, with a line on when to reach for it rather than a paraphrase of the RFC.
The client may send the body it asked about.
The upgrade to WebSocket was accepted.
It worked, and the body is the result.
A resource now exists; put its URL in Location.
Queued. The work has not happened yet.
It worked and there is nothing to send back. A DELETE, usually.
The range the client asked for, for resumable downloads.
A per-item result for a batch. Almost nothing understands it; a 200 with a result list is what people ship.
The URL changed for good. Search engines move their index.
A temporary redirect that may switch the method to GET. Prefer 307.
After a POST, send the client to a page it should GET.
Their cached copy is still good. No body.
Temporary, and the method and body are kept.
Permanent, and the method and body are kept.
The request itself is malformed. Not for a failed validation rule.
No credentials, or bad ones. It means unauthenticated.
Reserved for years, now used by APIs for a plan that has run out.
Authenticated, and still not allowed.
No such resource, or you are hiding its existence on purpose.
The URL exists; that verb does not. List the ones that do in Allow.
The client took too long to send it. Often a proxy talking, not your app.
The state moved under them: a duplicate, or a stale version.
It existed and will not come back. Kinder to crawlers than a 404.
The body is over your limit. Say what the limit is in the response.
The URL is over the server's limit, which usually means a query that wanted to be a POST.
The Content-Type is not one you take.
A joke from 1998 that refuses to die. Never ship it.
Well-formed, but the rules say no. The one to use for validation.
Someone else is holding it. WebDAV by origin, borrowed by editors and CMSs.
A replayed early-data request you would rather not process.
The protocol or version you are on is no longer accepted.
You want the client to send If-Match so two writers cannot overwrite each other.
Rate limited. Send Retry-After, always.
Usually one enormous cookie.
Removed by law rather than by choice. The number is a Bradbury reference.
You broke. Log it, and never leak the reason.
The server does not know this method at all.
Something upstream answered with nonsense.
Down or overloaded, and expected back. Send Retry-After.
Something upstream never answered.
A captive portal, not your API. Airport wifi speaking.
401 means unauthenticated: no credentials, or bad ones, and the client should try again with some. 403 means authenticated and still not allowed, so trying again with the same identity changes nothing. If you send 401, send a WWW-Authenticate header with it; that is what the status is defined to mean.
400 for a request that is malformed: broken JSON, a missing required field, the wrong shape entirely. 422 for a request that parsed fine and failed your rules, which is most validation. If your framework only offers 400, that is fine too; what matters is that the body says which field failed and why.
308 for permanent and 307 for temporary: both keep the method and the body. 301 and 302 are older and may turn a POST into a GET, which is rarely what anyone wants. For a browser navigation the difference rarely shows; for an API it changes what arrives.
200 when there is a body worth reading. 201 when something now exists, with its address in a Location header. 204 when it worked and there is nothing to say, which is the usual answer to a DELETE. A 204 with a body is a contradiction, and some clients will drop it.
404 says not found, which leaves open that it might turn up later. 410 says it existed and will not come back. Crawlers treat 410 as final and drop the URL faster, so it is the kinder answer for a page you deliberately retired.
When the request is valid but the current state refuses it: a duplicate email on signup, an edit against a version that has since moved, a resource someone else already claimed. 409 tells the client to re-read and try again rather than to fix its request.
429, always with a Retry-After header, in seconds or as a date. Without it every client invents its own backoff, and the polite ones end up punished. 503 also takes Retry-After and is for the whole service being unavailable rather than one client asking too often.
500 is your own code failing. 502 is something upstream answering with nonsense. 503 is you being down or overloaded on purpose, and it should carry Retry-After. 504 is something upstream never answering at all. The last three usually come from a proxy rather than from your application.
405, with an Allow header listing the methods that do work. Answering 404 hides a routing mistake and sends the client looking for a typo in the path that is not there.
For a plain REST endpoint, no: monitoring, caches, retries and every client library read the status first, and a 200 tells all of them nothing went wrong. The genuine exceptions are protocols that carry their own error channel, such as GraphQL, where a 200 with an errors array is the specified behaviour.
304 means the copy the client already has is still good, so the server sends no body. It happens when the request carried If-None-Match or If-Modified-Since and matched. If you are changing a file and seeing stale content, that exchange is usually why, and a changed ETag or a new URL is the fix.
404 when the existence of the resource is itself private, which is the usual choice for another tenant's data: 403 would confirm it exists. 403 when the resource is plainly public knowledge and the user simply lacks the right, such as an admin page. Whichever you pick, be consistent, or the difference becomes an oracle.
207 exists for exactly this and almost nothing understands it. In practice return 200 with a per-item result list, and document that the caller must read it. Returning 400 for a batch where nine of ten items succeeded throws away the nine.
Because there was no response to read: a CORS preflight that failed, a request the network dropped, or one the page aborted. The server may well have answered fine; the browser refused to hand it over. Look at the console and the preflight rather than at your status codes.
200, 201, 204, 301, 400, 401, 403, 404, 409, 422, 429 and 500 cover almost every response a normal API sends. The rest of this list is for the day something odd turns up in a log.