The Complete Guide to Status Codes for Meaningful ReST APIs (3 Part Series)
Photo by Joanna Kosinska on Unsplash
For more than 10 years we've been working with HTTP and APIs following the ReST architecture. Most people think that APIs are just interfaces you can use to interact with some third-party program and that ReST is all about HTTP verbs, however, most of the communication we use nowadays may be wrong just because we are using wrong HTTP status codes to express our responses. And this can be a life changer when we're talking of modern web applications.
That's right! An API is much more expressive than just writing GET to fetch data or POST to create data, this is the request part, what about the response?
In this article, we'll explore a bit more about HTTP Status Codes, when to use each one of them and their definitions! So, let's dive in!
- What are HTTP Status Codes?
- Code Classes
- Why do I need to know them?
Picking the right code for your API
- Most Used API Codes
- Coffee Break
Every protocol we use today has been defined and specified in a document we call Request For Comments, or simply, RFC, HTTP Status Codes are defined along with the HTTP protocol itself within the RFC2616, the document that defines what is HTTP/1.1, more specifically, on section 10. They're also defined on the RFC7231 section 6 about HTTP/1.1 Semantics. They're a number code that varies from 100 to 500ish and aims to make the HTTP response more meaningful to the client.
Incredible, we've cited the whole history of the Internet just to get a definition, right? But what does it mean? Every time we click on a button and send a request to a client-server-based application, this application answers us with another HTTP-based response, both the request and the response contains a header, which is responsible for giving us the context of that requisition. Status codes come on every response in a header called
Status (how original), and they are there just to give us a clue of what happened to our request after it's been processed.
Most of the time, common users won't see those status codes – unless something went terribly wrong – but, for us, programmers, they're extremely valuable. For instance, every time we cannot find a resource or a webpage we're presented with a 404 error page, this 404 is the HTTP status code for Not Found.
In short, they give us more information about what's happening and what has happened to the request we made, and they're pretty valuable to front-enders who want to show the correct status messages based on what the server has answered.
As we mentioned earlier, HTTP Status Codes are numbered from 100 to 500, however, this interval is not entirely filled, for example, we do not have a 174 status code because this was made to split codes into categories. These categories are defined in hundreds, each hundred of the HTTP interval represents a different category or class:
- 100s: These are informational codes, just to acknowledge that the request has been received and it's being processed.
- 200s: Success codes, returned when everything has been processed or understood properly, generally, this means that the client does not need to perform any more actions
- 300s: Redirection codes, meaning that the client should request that resource somewhere else
- 400s: Client error codes, when the client messed things up
- 500s: Server error codes, when the server messed things up
Status codes are not only important to programmers because we need to know what's happening so we can perform validations or error messaging, but also they're important to monitor the health of our application, as well as SEO.
In monitoring, is easier to know the health of an application by its status code, for example, if your website is returning a lot of 404s, probably someone messed up and forgot to put some page online, however, if your application is displaying a lot of 500s, it is probably offline and no one can use it. So it is a lot easier for the dev team to debug an application when it displays the correct information.
On the other hand, out of the dev environment, when we talk about SEO, status codes are the only way the crawling bots can understand what is happening when they "see" your website. This means that, if you're a blind robot that only understands status codes then if a page keeps returning 404, this means that this page is not very good since it does not exist, so its rank should be lower than other pages that return a 200 status code because they DO exist.
In this section, we'll go through all the defined status codes and their meanings, but we'll do it differently. Let's split this section into three:
- Most used API codes, where we'll talk about the codes we already use and how should we use them properly
- Codes not-so-often used, but we should use it more
- Other codes, where we'll finish the guide explaining less used status codes, which doesn't mean they're useless – except for one
In this article, we'll cover just the first part so it is not a very loooong reading for all of you! But, in the next articles of the series, we'll be covering the other two parts!
First of all, let's dive in the most common stuff, there won't be much new content here, after all, they're already mostly used. So let's go through the most common of the status codes by classes:
I believe this is the most common status code ever returned
The 200 OK is the standard response for successful requests. Generally, this is what we are eager to see. However, the response for this code should differ from an HTTP Method to another as described in the RFC7231.
When to use it: Generally there's another HTTP Status Code that would express what you want to say in a better way, but, if you have doubts about what HTTP code to use and your response is a success, then 200 it is!
This status code is usually used along with the
POST method since it describes a resource that has been created into the server after the successful fulfillment of the request.
When to use it: When creating stuff. For example, when you create a new user in the database, the response should be 201 with the newly created document as the body.
Used when the resource you're looking for has been permanently moved to another location. This status code usually comes along with another header telling the exact location where the resource has been moved.
When to use it: Normally used for permanent redirections, for instance, a website that has an index page on
http://contoso.com and should be redirected to
http://foo.com. But the catch is, this status code should only be used with GET or HEAD request methods, for all other methods we should use 308
Despite the text "found" don't give us much clue of what this is all about, the 302 status code is commonly used by temporary redirects, telling that the resource has been moved but it has been found on another URI described in the
When to use it: Mostly the same thing as 301, but used on temporary redirections where the resource will eventually be found in the current URL again. However, the rule applies, this status code should only be used with GET or HEAD request methods, for all other methods we should use 307
This status code is the official representation of the phrase "don't know, don't care". Since it only says that the server has found an error in the client's request and was unable to process it. The biggest mistake of most web developers is to return this error for EVERY request that they cannot handle. Which reduces the amount of information given to the client and, therefore, the meaningfulness of the API.
When to use it: When you have tried everything and still could not find what was wrong with the request. Otherwise, please use a more meaningful error code.
When to use it: When a resource cannot be accessed due to authentication reasons, normally used in login pages when the user tries to log in with a wrong user/password
When to use it: Generally used when we have a boundary to what users can do in the application, for instance, if I'm not the admin I should not be allowed to delete other users, therefore, if I try to do so, I'll get a 403 - Forbidden error. The rule of thumb is to remember the following sequence:
- If I don't know who is making the request, then it's 401 - Unauthorized
- If I do know who's making the request, but the user doesn't have permissions to do so, then it's 403 - Forbidden
The 404 status code is the most familiar to everyone, even those who are not devs. It is pretty straight forward, the resource you were looking for could not be found on this site.
When to use it: When you cannot find a page or resource, a not-so-known use case is to return 404 when a find query – like
/users/1234 – returns null. This is a good practice because the user was looking for a specific resource and it does not exist. On the other hand, if you're on a search query – like
/users – where you could return 0 or more then the default response for "There are no users registered" or "Empty list" would be 200.
Generally, when we don't implement a route but it is there, we use the 405 status code. This code says that the method we're using is a known method to the server – which means it can process it – however that particular resource does not accept it.
When to use it: Let's explain by example. If you have a
POST /users and a
GET /users but do not have a
DELETE /users, then if I try to
DELETE /users you should return a 405 status code to me, this status code generally comes along with another header called
Allow stating which methods are allowed.
The classic "Are you trying to DDoS me?". The 429 status code is defined on another RFC, the RFC-6585 for additional HTTP headers. It states that the requester has sent too many requests in a given amount of time, this is what we call rate limiting.
When to use it: This should be the default to all APIs out there that don't want to be crashed by DDoS attacks, but, since this is not the case today, the most common use case to this status code is to limit the number of requests that a user can make before it is blocked by the server. Most API gateways and user-exposed APIs use it, like Twitter, for instance, which allows about 15 requests per minute.
Also, if you're looking to do it yourself, Azure has a pretty cool tool that makes it possible
The classic "I messed things up". This status code is sent as the response when the server did something wrong on its side and do not know how to proceed. If a user is seeing this, then your application is in bad shape, since these status codes should be visible only to the internal side of the application. The user side should format the error and show a more user-friendly message.
When to use it: When an exception is thrown by the server and not caught and you do not know what happened, but you do know it is on the server. I've seen a lot of people using 400 status codes to show server-side errors, this is wrong on so many levels...
This status code is meant for proxied servers. It states that the server which is acting as a gateway or a proxy could not complete the request, or it received an invalid one from the client.
When to use it: The programmer should never need to use it manually unless you're writing a proxy API or a proxy server, in this case, you need to return this message instead of the 500 error we mentioned earlier.
The 503 code is more of an information code than an error one since it states that the server handling the requests is not available due to an overload or scheduled maintenance. In the case of the latter, the server can optionally send a
Retry-After header with an amount of time so the user can try again.
When to use it: As I mentioned on the other 500x errors, this code is usually not set by programmers since it is on server-side code, unless you're the developer of a server, in this case, the use case is pretty obvious.
When to use it: This code should be only returned if you're coding a gateway and the proxied server did not answer your request.
Stop for now! Grab a coffee as you prepare for the next part of this series, where we'll talk about the APIs we don't see very often, but we should.