Coding Standards
HTTP Status Codes
Foundational
The status code is the result of an HTTP request. It tells the client, and every proxy, cache, and monitor in between, what happened — before anyone reads the body. Pick the most specific code that is accurate. This is a reference to go with REST API Conventions.
Every response carries a three-digit status code. The first digit gives the class (was it a success, a redirect, the client's fault, or the server's?). The rest narrows it down. Clients, browsers, proxies, and load balancers all act on the code, so getting it right is part of the contract, not a cosmetic detail.
The tables below list the standard codes and what each is for. You will only use a handful day to day; the rest are here so you can choose correctly when you need them.
The five classes
Each class has a general meaning. When in doubt, get the class right first, then pick the specific code.
| Class | Meaning |
|---|
| 1xx | Informational. The request was received and the process is continuing. Rare in normal APIs. |
| 2xx | Success. The request was received, understood, and accepted. |
| 3xx | Redirection. Further action is needed to complete the request, usually following a different location. |
| 4xx | Client error. The request was wrong (bad input, not allowed, not found). Repeating it unchanged will fail again. |
| 5xx | Server error. The request looked valid but the server failed to handle it. It may be safe to retry later. |
Using them well
- DoPick the most specific code that is accurate. A 422 for a semantic validation error is more useful than a blanket 400, and a 409 for a conflict is clearer than a 400.
- NeverReturn
200 OK for a failed request. A 200 with an error in the body hides the failure from clients, proxies, caches, and monitoring (see REST API Conventions).
- DoUse 4xx for the caller's mistakes and 5xx for ours. The split tells clients whether retrying unchanged could ever help, and tells us whether an alert is our problem to fix.
- DoReturn
429 with a Retry-After header when rate-limiting, and 503 with Retry-After when temporarily down (see Rate Limiting & Abuse Prevention).
- AvoidInventing non-standard codes or reusing a code for a meaning it does not have. Stick to the registered codes below so clients and tools behave predictably.
- NeverUse the status code to leak internal detail. Pair the right code with a safe Problem Details body — never a stack trace, SQL, or file path (see Error Handling).
1xx — Informational
| Code | Use it for |
|---|
| 100 Continue | The client may continue sending a request body after the server accepted the headers. Handled by the stack, not set by hand. |
| 101 Switching Protocols | The server agrees to switch protocols (for example upgrading to WebSockets). |
| 102 Processing | (WebDAV) The server has accepted the request but has not finished. Rarely used. |
| 103 Early Hints | Lets the client start preloading resources while the final response is prepared. |
2xx — Success
| Code | Use it for |
|---|
| 200 OK | The standard success response for a request that returns a body (for example a GET). |
| 201 Created | A new resource was created (for example after a POST). Return a Location header pointing at it. |
| 202 Accepted | The request was accepted for processing but is not done yet. Use for asynchronous work; give the caller a way to check progress. |
| 203 Non-Authoritative Information | The response was modified by a proxy. Rarely set deliberately. |
| 204 No Content | Success, with no body to return (for example a DELETE or an update that returns nothing). |
| 205 Reset Content | Success; the client should reset the form or view that made the request. |
| 206 Partial Content | A range request succeeded and only part of the resource is returned (for example resumable downloads). |
| 207 Multi-Status | (WebDAV) Multiple independent results in one response body. |
| 208 Already Reported | (WebDAV) Members already listed in a previous part of a multi-status response. |
| 226 IM Used | The response is the result of applying delta encodings to the resource. Very rare. |
3xx — Redirection
| Code | Use it for |
|---|
| 300 Multiple Choices | The resource has several representations and the client may choose. Rarely used. |
| 301 Moved Permanently | The resource has a new permanent URL. Clients and search engines should update their links. |
| 302 Found | A temporary redirect. The method may change on the redirect, so prefer 307 or 303 when the method matters. |
| 303 See Other | After a POST, redirect the client to GET a different resource (the post/redirect/get pattern). |
| 304 Not Modified | The cached copy is still valid. Returned for conditional requests (If-None-Match / If-Modified-Since); send no body. |
| 307 Temporary Redirect | A temporary redirect that keeps the original method and body. Prefer over 302 when the method must be preserved. |
| 308 Permanent Redirect | Like 301, but keeps the original method and body. |
4xx — Client error
| Code | Use it for |
|---|
| 400 Bad Request | The request is malformed or cannot be understood (bad JSON, missing required field). The general client-error fallback when nothing more specific fits. |
| 401 Unauthorized | No valid authentication was provided. The caller is not signed in (the name is historic; it means unauthenticated). |
| 402 Payment Required | Reserved for payment flows; used by some billing APIs. Otherwise avoid. |
| 403 Forbidden | The caller is authenticated but not allowed to do this. Do not reveal whether the resource exists if that itself is sensitive. |
| 404 Not Found | The resource does not exist, or the caller should not know it does. Useful to hide existence from users who lack access. |
| 405 Method Not Allowed | The URL exists but not for this HTTP method. List the allowed methods in an Allow header. |
| 406 Not Acceptable | The server cannot produce a response matching the client's Accept headers. |
| 407 Proxy Authentication Required | Like 401, but authentication is needed for a proxy. |
| 408 Request Timeout | The client took too long to send the request. |
| 409 Conflict | The request conflicts with the current state (a duplicate, or an edit against a stale version). Use for optimistic-concurrency clashes. |
| 410 Gone | The resource used to exist and has been permanently removed. More specific than 404 when you know it is gone. |
| 411 Length Required | The request must include a Content-Length header. |
| 412 Precondition Failed | A condition in the request headers (for example If-Match) was not met. |
| 413 Content Too Large | The request body is larger than the server will accept. Enforce a size limit. |
| 414 URI Too Long | The URL is longer than the server will accept (often too many query parameters). |
| 415 Unsupported Media Type | The body's Content-Type is not supported (for example XML sent to a JSON-only endpoint). |
| 416 Range Not Satisfiable | The requested range cannot be served (for example beyond the end of the file). |
| 417 Expectation Failed | The server cannot meet the request's Expect header. |
| 418 I'm a Teapot | An April Fools' joke code. Never use it in a real API. |
| 421 Misdirected Request | The request reached a server that cannot produce a response for it. |
| 422 Unprocessable Content | The syntax is valid but the content fails business validation (for example a date in the past where a future date is required). The usual choice for validation errors on a well-formed body. |
| 423 Locked | (WebDAV) The resource is locked. |
| 424 Failed Dependency | (WebDAV) The request failed because a previous request it depended on failed. |
| 425 Too Early | The server will not process a request that might be replayed. |
| 426 Upgrade Required | The client must switch to a different protocol (for example a newer TLS version). |
| 428 Precondition Required | The server requires a conditional request, to stop lost-update clashes. |
| 429 Too Many Requests | The caller has been rate-limited. Include a Retry-After header. |
| 431 Request Header Fields Too Large | The headers are too large for the server to process. |
| 451 Unavailable For Legal Reasons | The resource is blocked for legal reasons (for example a court order or sanctions). |
5xx — Server error
| Code | Use it for |
|---|
| 500 Internal Server Error | An unexpected fault in our code. The general server-error fallback. Log it; never leak the detail to the caller. |
| 501 Not Implemented | The server does not support the functionality to fulfil the request (for example an unimplemented method). |
| 502 Bad Gateway | A gateway or proxy got an invalid response from an upstream server. |
| 503 Service Unavailable | The server is temporarily overloaded or down for maintenance. Include a Retry-After header where you can. |
| 504 Gateway Timeout | A gateway or proxy did not get a response from an upstream server in time. |
| 505 HTTP Version Not Supported | The server does not support the HTTP version used in the request. |
| 506 Variant Also Negotiates | A content-negotiation configuration error on the server. |
| 507 Insufficient Storage | (WebDAV) The server cannot store what is needed to complete the request. |
| 508 Loop Detected | (WebDAV) The server detected an infinite loop while processing. |
| 510 Not Extended | Further extensions to the request are required. |
| 511 Network Authentication Required | The client must authenticate to gain network access (for example a captive portal). |
Self-review checklist
- AskIs this the most specific code that is accurate, not just the first one that came to mind?
- AskIs a failure returning a 4xx or 5xx — never a 200 with an error in the body?
- AskDoes a 4xx really mean the caller's mistake, and a 5xx really mean ours?
- AskFor 429 and 503, did I include a
Retry-After header?
Why it matters: The status code is the part of the response that clients, proxies, caches, retry logic, and dashboards all read first. The right code lets a caller handle success, retry a transient fault, stop retrying a bad request, and follow a redirect — without parsing the body. The wrong code (especially a 200 on failure) hides problems and breaks every layer that trusts it.