Thursday, May 31, 2012

Designing RESTful APIs

A restful castle


During a customer call today, I bumped on to a question about standards of RESTful API implementations. This intact is a quite a tricky question, because REST is actually an architectural style, not a protocol specification. To prove the point, you may take Twitter, Facebook, LinkedIn, or any other popular RESTful API for that matter, non of them has similar protocol specification.

My approach for REST API design is to study few of these latest and popular APIs to derive a style that matches my needs. In this post I thought of sharing my expierience and thoughts on what I believe is a quite elegant RESTful implementation if someone needs a starting point. Note that these are not standards and I'm prepared to be challenged if someone convinces me otherwise.

Use of HTTP methods and URLs

Unlike SOAP RPC which encourages developers to define actions with verbs + nouns [ e.g. getAllStudents() ], REST proposes keep these 2 separated. REST utilizes common HTTP methods GET, POST, PUT, DELETE to inform server about type of CRUD action to perform. Additionally the URLs are used to identify the data entity/container on which the action should be performed. Following table depicts a simple structure of REST requests for someone to use.


GET (Retrieve)
POST (Create)
PUT (Update)
DELETE (Delete)
api.my.net/students
Get all students
Create a new
Bulk update
Delete all
api.my.net/students/1242
Get 1242
-Invalid-
Update 1242
Delete 1242

But in real life projects, not everything is a CRUD operation. For such situations we may use URLs that uses action verbs instead of nouns. 
An example would be "/api/interest/calculate?rate=15&capital=100&period=2".

Use of HTTP Headers

I believe RESTful services should also make use of the HTTP headers elegantly, ensuring that URLs and Payload data are not cluttered.
  • For example, the protocol format could be defined in the HTTP header (content-type: 'application/json') rather than being a part of the URL (e.g. /students?type=json) 
  • Also it's important to perform caching on the client side to avoid unnecessary content transfers and rendering. Clients should use If-Modified-Since header where server may respond with 304 (not modified) if no modification available. 
  • Incase of exceptions server may respond with 404 (not found) when client request is erroneous and 500 (sever error) incase something unavoidable happens on the server. I prefer this approach compared to payload driven error handling implemented in Facebook API.

Use of Content

It is easy to overlook this aspect, resulting a non readable, non consistent REST API.
  • For example, it is important to agree and document how should the JSON entity structure should look like for collections. Although I'm yet to use, it could be a good idea to use 'JSON Schemas' to define and validate the agreed message formats. 
  • Also it is important NOT to make the payload too verbose. For that matter, I discourage use of JSON structure to transfer binary content. Instead JSON response may contain hyperlinks to mark related documents, images, etc. 
  • Generally developer code SDKs are very much fine grained. If these are directly exposed as REST APIs, the client-server communicate could become chatty and expensive. It is recommended to use an abstraction layer on top of the SDK layer to adapt more corse grained services to be used for the REST API.

Support evolution of your API

Versioning is always a debatable subject on services. Ideally all APIs should be backward compatible but unfortunately i'm yet to find that ideal project. In REST way, an entity should have a permanent URL regardless of the version. But for previous versions of the API you could keep limited, short life spanned urls with version number attached.

Permanent URL: http://api.my.net/students/1234
Deprecated/Beta URL: http://api.my.net/v3/students/1234

Clients should always use the permanent URLs, but incase of backward compatibility breach, client may temporally indicate the API version on its HTTP request header. Server can then do routing/transfers to serve the client with the correct API version.

Hopefully you are now convinced to spend sometime in agreeing the basics of your protocols specification before jumping on implementation. As said above REST is just an architectural style, you need to decide the protocol specs before you implement.