REST API Design Principles

Collections and objects

For REST APIs there are two key roles: Collections and objects. Every RESTful URL is build up of a varying combination of those two components. Let's look at an easy example.

http://www.egyptian-bazaar.com/camels/1  

We are back again with the camels example (don't ask me why I harp on about those camels, it just happens). Here we have the collection represented by /camels and the object represented by /camels/1. So if we want to retrieve a list of camels (say collection), we use the /camels path and if we want to retrieve one particular camel with the identifier 1, we use the /camels/1 path.

Let's enhance that example to make the web service even more useful.

http://www.egyptian-bazaar.com/camels/1/humps/2  

If you make a GET request to that URL, you could retrieve an object for the hump with the identifier 2 of the camel with identifier 1. The object will include all information related to that hump. Like filling quantity. Oh my...

There are discussions raging out there, if the representation of collections should be in singular or plural. I don't want to put more fuel into it. Use the plural version. Flames are rising into the sky.

The different request methods

There are quite some request methods (also called HTTP(S) verbs) out there. To see a list of all of them I would recommend to read the official RFC 2616. I will only cover the four methods that will be used most often in the design of RESTful APIs.

GET method

The GET method is the most frequently used one in the Internet today. You ask yourself how I can know that? I asked myself the same question while writing that bold claim. Let's put it that way: every website you visit requires a lot of GET requests to retrieve the different html documents, images, styles and scripts. If you start looking at the network section of the Chrome Inspector you will immediately note, how many GET requests are necessary to fully load the website of your choice.

But back to topic: You will use a GET request to retrieve information from the API. So if you want to retrieve all camels currently available, you would do a GET http://www.egyptian-bazaar.com/camels.

A GET request will never change anything on the server and will always return the same result (as long as no other request did change something in the meantime). This characteristic is called idempotent (just in case you want to show of in front of your friends with some fancy words). By the way: even though all HTTP(S) requests can include a request body, you should never provide any data in the body of a GET request. Never.

Mind the cache: A browser could and will cache GET requests, if you do not take counter measures against that. The most trivial solution is to make sure to include a parameter that makes the request unique.

GET http://www.egyptian-bazaar.com/camels?nocache=123456  

You can use whatever parameter you like, just make sure to use a unique one with every request that you don't want to be cached.
Alternatively, most of the Javascript frameworks out there provide methods to disable caching for AJAX requests like for example JQuery:

$.ajax({
  url: "http://www.egyptian-bazaar.com/camels", 
  cache: false
});

A whole new chapter would be the use of ETags, but that is something you could get into on your own by spending some time on Wikipedia.

POST method

A POST request will most likely contain data in the request body and change the data on your server. Therefore it will not create the same outcome when sending the request multiple times. You got it: it is not idempotent.

POST requests are often used to create new objects on the server. So if you want to add a new camel to your collection of camels, you can use the following POST call:

POST /camels HTTP/1.1  
Host: egyptian-bazaar.com  
name=Carlos&age=35&color=Champaign-Silver  

I won't elaborate on POST requests in relation to camel humps, since this would lead to serious questions about ethics in genetic manipulation of camels and would most probably bring up animal rights activists against me. Scary.

If you want to describe a POST request in a more natural language, you would say: "Add a new camel with the given attributes to the list of camels". That is one of the reasons why I recommended to use the plural form for collections. It just sounds awkward to say: "Add a new camel with the given attributes to the list of camel". I call that bombproof argumentation.

DELETE method

Does what it says: it deletes an object from the server. The syntax is as easy as for a GET request:

DELETE http://www.egyptian-bazaar.com/camels/2  

This would delete our Carlos from the collection of camels. Bye Carlos.

PUT and PATCH method

PUT and PATCH are available for similar reasons: to modify an existing object on the server. The difference lies in the body of the request. While PUT sends the whole object representation to the server (so the server only has to replace the old version with the new one), PATCH uses its own syntax to tell the server which properties of the object to modify. There is a very own syntax available in RFC 6902 that would exceed the scope of that article.

The right response code

I want to shortly talk about response codes at the end and in particular about the success response codes, since I used them improperly for quite a long time without knowing the differences.

200 Ok
Use the 200 status code, if the request was successful and if the server wants to include data in the response.

201 Created
If the server created a new object (in most cases after a successful POST request) the response to the client would have the 201 status code and some form of data in the response body that tells the client how to find the newly created resource.

204 No Content
If there is no data that must be returned to the client after a successful request, use the 204 status code without a response body.

For a more detailed explanation on HTTP(S) status codes I recommend to have a look at the status code definition section of RFC 2616. If you have any questions left, feel free to contact me.

Thanks for reading and have a great Easter weekend!