Tuesday, September 2, 2014

How to create a Web API no one wants to use. Part 5: Versioning

Introduction to this blog series


Later this year, Netflix will be closing their public APIs. Twitter and Google have already restricted their APIs. Despite prominent tech-companies making drastic changes to their APIs, the number of APIs keeps growing steadily. Suddenly, everyone has a Web API. Your car has one, Chuck Norris has one, and worst of all, tech-companies with no focus on quality whatsoever has one. And who are using these APIs? Most likely, no one.
This blog series will take you through the pitfalls of creating a Web API. From a developers perspective, what mistakes will result in no one wanting to use your API?

Part 1: URI Design
Part 2: HTTP Verbs
Part 3: HTTP Status Codes
Part 4: Result formatting
Part 5: Versioning
Exercises

Versioning

One of the first things you should think about when creating a Web API is how to handle versioning. However perfect you make your API, you're bound to find a way that's even more perfect before long, and then you'll need to launch a new version. If you haven't already planned out how your versioning should work, the lauch of a new version might be painful for the developers consuming your API. 
As RESTful APIs are growing in popularity and we see the number of SOAP APIs decreasing, my impression is that the focus on version handling is becoming better. Where developers previously put a number at the end of their method name, they now decide on an overall strategy for their API. 
Example: PayEx API
An example of the terrible "I'll just put a number at the end" versioning that arised with SOAP can be seen for example in the PayEx API. If we have a look at the PxOrder webservice, it contains the following methods: 
  • Cancel2
  • Capture5
  • Check2
  • Complete
  • Credit5
  • CreditOrderLine3
The developers consuming your API have no way of knowing whether the Cancel2 method is compatible with the Capture5 method, and this makes your API difficult to work with! 
So, what is the correct way of versioning your API? There isn't one. There are several possibilities, but there isn't 'one' correct that you should be using. Whichever way you pick, someone will claim that the one you picked is wrong, so pick the one you feel makes the most sense for your API. What's important is that a new version should not break the existing versions for the users of your API. 
Solution 1: URL versioning
Putting the version number in the URL is a quite popular approach. One of the APIs that does this is the Twitter API
GET https://api.twitter.com/1.1/trends/place.json?id=1
The upside of URL versioning is that you can quite easily change the structure of your API in the next version without breaking any changes for users wishing to stay with an older version. In addition to this, there is never any confusion as to what version of the API you are using, you can send the URL to someone else and they will see the same version of the API as you. The downsides to this approach is that you might have to maintain quite a large number of URLs as time goes by, and clients wanting to upgrade to a newer version will have to change all their URLs. Last, but not least, there is no way for the developers consuming your API to say: "Always give me the newest version of your API". Instead they have to say "Give me version X of your API".  
Solution 2: Query string parameter
Including the version number as an optional query string parameter makes it possible for developers consuming your API to always get the newest version. An API that lets you do this is the Netflix API
GET http://api-public.netflix.com/catalog/titles/series/7002352?v=1.5
Others prefer to use the date of the version release instead of the version number, for example FourSquare:
GET https://api.foursquare.com/v2/venues/40a55d80f964a52020f31ee3?oauth_token=XXX&v=YYYYMMDD
In both cases, leaving out the version query string parameter will result in the newest version being used. And creating a new version will never change the URL, only the query string parameter changes. This kind of versioning is great when the changes done from version to version are small. If there are any breaking changes from one version to another, and the users of your API are using the latest version, you might be breaking their code. "Breaking changes", get it?
Solution 3: Vendor Specific Accept Header

In part 4 of this blog series, we saw how we could use Content Negotiation with Accept headers for determining the result formatting. The same can be done for versioning, and it's often used in combination with result formatting in what we call "Vendor Specific Accept Header". The format for this is:
HEADER Accept: {type}/vnd.{company}.{version}+{type}

The GitHub API for example uses:
HEADER Accept: application/vnd.github.v3+json

This Accept header tells us that we want the results as application/json, and we're using version 3 of the API. By using Vendor Specific Accept headers, all URLs will be the same for any version of the API, which is good since one resource should only have one URL. However, there are some downsides to this approach as well. Changing the headers is not always a walk in the park, so it might make the API harder to use for some developers.
Solution 4: Custom Request Header

Instead of using the Accept Header as we saw in the previous example, some APIs create their own Custom Request Headers. An example is the Azure Storage Services API:
HEADER x-ms-version: 2014-02-14

The upside of creating your own Request header is that the version request header only determines the version. In our previous example of using a Vendor Specific Accept header, the type also had to be included. Again, all URLs will be indentical for any version of the API, but we still have the same issue of request headers not always being easy to modify.

Solution 5: All of the above?

If you're feeling really awesome, you can follow the example of Troy Hunt. He decided that since every type of versioning would be considered wrong by some, he would implement three different ones in his API to please the crowd. His blog post "Your API versioning is wrong, which is why I decided to do it 3 different wrong ways" is definitely worth a read!

Summary


Versioning is difficult as everyone has different opinions as to which way is the "right" way. What's important though is that you decide on a versioning strategy from day one so that it doesn't come as a surprise to you later when you decide to improve your API. Whatever you do, DO NOT break your clients code! And of course, care about your API from the very first piece of code you write.

No comments:

Post a Comment