Version your RESTful API responses

In my previous post, I discussed the idea of adding sync to your RESTful API through a predictable and an already existing interface. This time, let’s take a look at how to go about versioning you API.

Usually APIs are versioned through the use of URIs, for instance:

https://api.example.com/v1/dogs

Whenever you introduce a new API version, you publish a new v2URI for all your endpoints and slowly stop supporting older ones. While common practice, this is not in alignment with REST:

The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components. By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved.
— Roy Thomas Fielding disertation, Chapter 5

The key here is that the URI for a specific resource should not change through its lifetime. A possible solution to this problem might be no versioning at all, but as you can imagine, this will not work for the majority of APIs.

Media types

Instead of versioning your API through the URI, keep you API endpoints unchanged and version your responses using custom media types in the Accept header of your requests, like so:

When the server sees an Accept header it can use the Factory pattern to return the correct response representation for the required resource version.

The media type specification allows you to extend the vendor tree, so you could include even more information about the expected response (like specific versions for all resource types your API provides).

If the developer doesn’t mind getting the freshest response from the API every time, they could set the Accept header to application/json instead. So whenever you update your API, those applications will automatically receive the freshest response versions.

Problems?

The proposed idea might be a stretch for some, but if you think about this problem from a purely software engineering standpoint, try to forget that the client is communicating with your API via a network. How different is this from communicating with an API over a local bus? So in this case a uniform interface is necessary. Imagine how stressful coding a driver would be if the API kept changing with each new release.