REST API Maturity Levels
Rafael Câmara
Posted on February 21, 2022
We all have worked with REST APIs. They are extremely simple and intuitive. But we might want to take a step forward in analyzing our APIs. We have metrics for everything in Software Engineering, for instance, code coverage, but what if we wanted something similar to evaluate our REST APIs. A "framework" that could help us answer the question: "How RESTfulness is my API?".
To help us is that demand, Leonard Richardson created the "Richardson Maturity Model". This model introduces four levels, which can be seen in the following figure. Think of each level as a step forward in achieving a truly RESTful API.
Level 0: Most people agree that if you have your API at this level, you don't even have a REST API.
At this level, you have a single URI that receives all the requests. You might ask: "How can a server know what to do if it only has a single endpoint?".
Since XML is broadly used in this scenario, inside the XML body we specify the operation that needs to be done, as well as the relevant data for that. This means that the necessary detail is inside our request's body.
This method is often called "The Swamp of POX", where POX means Plain Old XML because everything is defined inside the XML, as we previously mentioned. Because we are sending our information in the body of our request, the most common HTTP verb used is POST (actually it doesn't matter which is the verb used, other people might use GET, we just need to be consistent and stick with one).
Keep in mind that, although we use POST to send information, we don't use the HTTP knowledge and constructs to effectively communicate.
Let's say we are building an API that manages stock in a local supermarket, which has the base URL of www.myfakesupermarket.com [at the time of this post, such URL does not exist, it was created by me for educational purposes].
Imagine that we want to add the product to our stock. Our request would be:
POST /stock HTTP/1.1
[various other headers]
<addStockProduct>
<product name="apple" quantity=200 />
</addStockProduct>
If we wanted to retrieve our apple stock, our request would be something like:
POST /stock HTTP/1.1
[various other headers]
<retrieveAppleStockInfo/>
Level 1: Starting level for REST API. We here introduce the notion of Resource URI, meaning individual URIs for each resource.
At this level, we have a mindset of "divide and conquer", meaning that we split our huge only endpoints into smaller fractions, where each fraction represents an endpoint (which itself represents a resource).
We would still have the information about the operation inside the request. Still, we use only one HTTP verb, being the most common one POST.
Continuing with the supermarket example, instead of having this main URI, we now will have several resources, each one identified by its URI.
Let's say we wanted to operate over the apples and oranges in our stock. Those resources URIs would be appended /apple and /orange, respectively, to the main URI.
Getting all the apples and oranges in stock would be, respectively, something like:
POST /apple HTTP/1.1
[various other headers]
<retrieveStockInfo/>
POST /orange HTTP/1.1
[various other headers]
<retrieveStockInfo/>
Adding an apple to our stock would be something like:
POST /apple HTTP/1.1
[various other headers]
<addStockProduct>
<product name="apple" quantity=200 />
</addStockProduct>
Notice that depending on the resource we want to operate on, we go to the according to the resource URI. If it is apples go to the apples URI (/apple), if it is oranges go to the oranges URI (/oranges), and so on. Compare this approach with the level 0 zero. We can argue that this one is better, but we still can improve.
Level 2: Most of today's APIs are at this level. We introduce the standard HTTP methods to operate on multiple URIs. Our HTTP verb specifies what we will be doing in that specific resource. Each verb was originally designed for one purpose and you use it for such purpose.
Besides using the correct HTTP verb, it is also important to have in consideration using the correct HTTP status codes in the responses.
Let's replicate the level 1 examples, so we can see how things change.
Getting all the apples and oranges in stock would be, respectively, something like:
GET /apple HTTP/1.1
[various other headers]
GET /orange HTTP/1.1
[various other headers]
As you can see, since we want to retrieve information, the appropriate HTTP verb to retrieve information is used (GET).
Adding an apple to our stock would be something like:
POST /apple HTTP/1.1
[various other headers]
<addStockProduct>
<product id="123 name="apple" quantity=200 />
</addStockProduct>
Level 3: In this level, we come across the acronym HATEOAS, which stands for Hypertext As The Engine Of Application State.
Let's start with a small example. Say we want to retrieve the products that are currently in stock. Our request would look something like:
GET /stock HTTP/1.1
Our initial request remains the same, but the only thing that is going to change is what we receive from the server, which is going to be something like:
<stock>
<product id="123" name="apple" quantity=200>
<link rel = "/linkrels/product/addStock" uri = "/stock/123"/>
</product>
</stock>
If the XML example was a bit confusing to understand, please refer to the following JSON example, not related to our stock example, but represents the response when you retrieve a specific account in a bank, for example.
As you can see, our response has a new field: link. In this field, we receive clear information from the server telling us what we can do next, and the specific URI of the resource that we can interact with. In our stock example, we receive the information that by using the same URI "/stock/123" we can addStock to that product.
Now analyze the JSON case. You can clearly see what you can do with a specific account. By using this approach, your API gains navigability.
A big advantage of this is that the client doesn't need to be aware of all the URIs, they will be sent to him in the response under the link section.
😁 I hope this has helped!
That's everything for now! Thank you so much for reading. For more in-depth information, please consider reading this article by Martin Fowler, which is very complete and well explained!
If you have any questions please feel free to drop them off.
Follow me if you want to read more about these kinds of topics!
Posted on February 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.