When it comes to the use of micro-services and APIs. It appears pretty common for a few key response codes to be used. However, if you look at the IANA Status Code Registry of defined codes, there a number of other very useful codes that can help convey issues clearly, without compromising security.
The IANA list references the relevant IETF RFCs, but I’ve taken this a step further and obtained the relevant deep hyperlinks to the code explanations. In addition to that, I’ve also highlighted some response codes, that perhaps benefit from a closer look, or considered with caution.
Value | Description | Reference | Comments |
100 | Continue | RFC7231, | |
101 | Switching Protocols | RFC7231, | |
102 | Processing | RFC2518 | This is a code I’m cautious of using unless all calls may be held open by using this response as if used intermittently if discovered during probing it could be ready as an indicator that the request made could deprive other users of access to the service. |
103 | Early Hints | RFC8297 | |
104-199 | Unassigned | ||
200 | OK | RFC7231, | |
201 | Created | RFC7231, | Better than just 200 |
202 | Accepted | RFC7231, | when confirming receipt of a request but not necessarily of the data being processed. |
203 | Non-Authoritative Information | RFC7231, | For REST use cases I’d personally avoid this, as REST principles say we shouldn’t know or care about proxys etc |
204 | No Content | RFC7231, | |
205 | Reset Content | RFC7231, | If you want the client to actively reset its view – use this |
206 | Partial Content | RFC7233, | |
207 | Multi-Status | RFC4918 | For WebDAV rather than normal REST use cases |
208 | Already Reported | RFC5842 | For WebDAV rather than normal REST use cases |
209-225 | Unassigned | ||
226 | IM Used | RFC3229 | Good to use if the response includes changes from other transactions as well |
227-299 | Unassigned | ||
300 | Multiple Choices | RFC7231, | When it comes to APIs our interfaces should not require disambiguation.
If you’re considering this response to an API, perhaps its time for a tolerant reader backend |
301 | Moved Permanently | RFC7231, | Tells the client about the addressing, but not how the request has been processed |
302 | Found | RFC7231, | |
303 | See Other | RFC7231, | |
304 | Not Modified | RFC7232, | This is a much-overlooked possibility. |
305 | Use Proxy | RFC7231, | For REST, we shouldn’t need or want to know about intermediaries. |
306 | (Unused) | RFC7231, | |
307 | Temporary Redirect | RFC7231, | For REST, we shouldn’t need or want to know about intermediaries. |
308 | Permanent Redirect | RFC7538 | For REST, we shouldn’t need or want to know about intermediaries. |
309-399 | Unassigned | ||
400 | Bad Request | RFC7231, | |
401 | Unauthorized | RFC7235, | Good way to be clear about authentication |
402 | Payment Required | RFC7231, | If you’re monetising the APIs – then a great code to use |
403 | Forbidden | RFC7231, | Meaningful developer feedback |
404 | Not Found | RFC7231, | Meaningful developer feedback |
405 | Method Not Allowed | RFC7231, | Meaningful developer feedback |
406 | Not Acceptable | RFC7231, | Meaningful developer feedback |
407 | Proxy Authentication Required | RFC7235, | Hints at infrastructure, I’d personally always just use 401 |
408 | Request Timeout | RFC7231, | |
409 | Conflict | RFC7231, | ideal if individual entities are being versioned as part of an optimistic locking pattern |
410 | Gone | RFC7231, | |
411 | Length Required | RFC7231, | |
412 | Precondition Failed | RFC7232, | |
413 | Payload Too Large | RFC7231, | |
414 | URI Too Long | RFC7231, | |
415 | Unsupported Media Type | RFC7231, | |
416 | Range Not Satisfiable | RFC7233, | |
417 | Expectation Failed | RFC7231, | |
418-420 | Unassigned | ||
421 | Misdirected Request | RFC7540, | |
422 | Unprocessable Entity | RFC4918 | Intended for WebDAV |
423 | Locked | RFC4918 | Intended for WebDAV |
424 | Failed Dependency | RFC4918 | Intended for WebDAV |
425 | Too Early | RFC8470 | Might suggest that the system is sensitive to data integrity |
426 | Upgrade Required | RFC7231, | a good way to reject API calls that are using out of date API versions or security protocols |
427 | Unassigned | ||
428 | Precondition Required | RFC6585 | |
429 | Too Many Requests | RFC6585 | A polite way of saying you’ve exceeded your call allowance and we’re rate limiting |
430 | Unassigned | ||
431 | Request Header Fields Too Large | RFC6585 | |
432-450 | Unassigned | ||
451 | Unavailable For Legal Reasons | RFC7725 | An interesting return code, and a nice way to reject calls without service agreements |
452-499 | Unassigned | ||
500 | Internal Server Error | RFC7231, | To be used with care – as it could indicate an attack is impacting the back end |
501 | Not Implemented | RFC7231, | |
502 | Bad Gateway | RFC7231, | Definitely indicative of internal issues |
503 | Service Unavailable | RFC7231, | |
504 | Gateway Timeout | RFC7231, Section 6.6.5 | |
505 | HTTP Version Not Supported | RFC7231, | |
506 | Variant Also Negotiates | RFC2295 | |
507 | Insufficient Storage | RFC4918 | Not a response code I would choose to use for a public API as it advertises how the service could be disrupted |
508 | Loop Detected | RFC5842 | Not a response code I would choose to use for a public API as it advertises how the service could be disrupted |
509 | Unassigned | RFC2774 | |
510 | Not Extended | RFC2774 | |
511 | Network Authentication Required | RFC6585 | Better to use the standard authentication error as this indicates how authentication is at-least impart implemented. |
512-599 | Unassigned |