Ask HN: Version numbers in a REST API
I'm in the final stages of designing a REST based API for my SaaS billing site, but I'm stuck debating whether I should include a version number (/1/clients/list) or not (/clients/list).
Obviously the latter is far cleaner and simpler, but am I shooting myself in the foot by leaving out the version number?
54 comments
[ 3.3 ms ] story [ 101 ms ] threadI did the same research some months ago and didn't find "the" solution or answer to this question.
Linkdump from my bookmarks to this topic:
Discussion: http://blog.sonoasystems.com/detail/one_size_doesnt_fit_all_... http://stackoverflow.com/questions/389169/best-practices-for... http://stackoverflow.com/questions/2024600/rest-api-versioni... http://stackoverflow.com/questions/972226/how-to-version-res... http://stackoverflow.com/questions/278686/versioning-restful... http://stackoverflow.com/questions/1679322/web-services-api-... http://stackoverflow.com/questions/2101566/what-are-your-web... http://barelyenough.org/blog/2008/05/versioning-rest-web-ser...
Examples: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference... http://atlas.resources.ca.gov/ArcGIS/SDK/REST/versioning.htm... http://groups.google.com/group/twitter-api-announce/browse_t...
Hope this helps a little bit.
Spent the last two hours looking for suggestions but didn't find half of what you just posted (probably because I was missing the key word 'versioning')
However, I would name them "v1", "v2" etc. That makes the purpose of the number clear.
https://api-v1.xxxy.com/clients/list
I believe its a little neater than /v1/clients/list, albeit a little less standard.
If I use the latest version it is likely developers will simple leave the header out since it "Just Works" without it.
Then when I make a breaking change to the latest API those applications will get screwed. Yes its mostly their fault -- but its my problem.
/api/getstuff?v=1.1&arg1=x&arg2=y
If the version isn't there just return a useful error.
The only downside to this is that it's slightly more difficult to do analytics on the URL requests coming in.
You can't believe how many time I have had problems with an API just to discover the 3 year old client library was using some "sensible defaults" for required arguments.
This is how Google handle it and I think it make sense. http://code.google.com/intl/zh-TW/apis/gdata/docs/developers...
I had to take packet snippers to XML appliances :-/
API versioning is a good thing, and the best way to choose a version is via a parameter. Don't ever ever try to to encode the version into the security token you return to the clients; someone did that for succinctness, so that you could choose a version once upon connection establishment. It was a nightmare to debug looking at the logs.
With API design, your good design decisions will be taken for granted, and your bad ones will me immortalized in a mountain carving. Try to model it after some existing API that offers a similar functionality, or use an extensible design like the SugarCRM SOAP API, or Zuora's SQL-like one.
E.g. if you are programming GData client, it suggest you to add version info (i.e. GData-Version: X.0 ) in the request header.
http://code.google.com/intl/zh-TW/apis/gdata/docs/developers...
I once saw a significant uptick in users being unable to use an AJAX application because a developer "fixed" the RPC stuff to sent Content-Type: application/json headers instead of claiming to be text/html.
Since it's REST, clients shouldn't be hardcoding any URLs aside from the API root. Therefore, if you think a version is ugly, you can make the sub-URLs unversioned for now and version them later if needed.
This would always point to the latest API version: api.example.com/clients/1/posts
If you want a specific version you do this: api.example.com/v1/clients/1/posts
Since we're using ASP.Net MVC we could register a 'route' which points api.example.com/ to the API v1 code. Then when /v2 comes out we just point it to that and v1 is still available.
If you were to go that way, I would recommend strongly encouraging developers to use the /v1/. "It's 3 extra characters to make sure that your app doesn't break one day because we upgrade the API." Obviously, you probably should make backwards-incompatible changes infrequently and only after communicating well with your developer community--otherwise developers will feel like they can't keep. But still, some people will miss the announcements or not have time to adapt in time.
That way, people who need to stay on old can add in the string, and those who can adapt will.
The v1 just doesn't seem to belong in that part of the url to me. Maybe if you had v1.api.example.com/coolstuff/1 - that I'd be more comfortable with.
In the end, it seems how APIs are versioned and supported completely depends on the maturity of your product. I imagine that eventually you want to get to the point where you're only adding to the API and not removing or reworking entire calls. And perhaps then you won't need the version numbers at all. But for now, they might be your only safety-net for your customers.
From an "academic" point of view, the versioning through http accept headers is considered the "best one".
I'm usually going with a path prefix as nearly everyone else does.
As you probably have a lot of API users that don't know and care about http accept headers (and their connection libraries usually don't either), it might be a lot of PITA to convince them doing it right.
So imho you can use the "academic" solution and hire some API Support stuff, teaching each customer the benefits and ways to access versioned resources — or just use the most obvious de-facto standard like /v1/posts/<id>.
That's why I use this compromise.
In Addition, the http accept header versioning allows you to version on each resource independently. This might be a good thing but usually the whole API changes and not only one resource (change as in incompatible change, not an addition of some attributes)
It seems there are two REST camps: academics and those who actually write real-world APIs.
http://barelyenough.org/blog/2008/05/versioning-rest-web-ser...
Namespacing by version also is pretty "clean." Imagine updating your API in the future without the namespace. You'd have to implement the version in some difficult way (for the end developer) such as during authentication or as a request param or cookie or something ridiculous. This all adds complexity to the developers using the API. Its _much_ easier for a developer to just say "The prefix for all RESTful API calls is http://foobar.com/v1. No developer will say thats not clean.
So please, put a version number in your API, put it at the beginning, and put it in the "vX" format.
The /v1/ is much better, and solves the problem.
I'm choosing the /v1/ route because its a neat solution to the problem, it will work without serious issues and developers understand it easily.
Yes its not 110% REST, but I believe its the best solution to my problem. The fact that other major API's are taking the same route (Amazon,Twitter) just enforces the idea.
Why? Assuming the author is actually using REST, worst case for updating is adding another resource somewhere. There should be no need to update client applications at all.
Updating is easy, just add the representations to the resources that need the newer version (eg, "views" in rails). Updating with a new v2 in your URI means updating ALL your resources, or writing lots of redundant code to route multiple incoming uris to the same resource. This gets unmanageable, fast.
Putting versions in the URI increases complexity, for you, and writers of clients.
Perhaps, but it you have tests for your api you can tell if you break them. Also, there is no reason you need to duplicate code if a section of the api didn't change. You only need to duplicate code if something major changes. Everything else can just be silently routed to the previous version's interface.
It doesn't add much value to give users a /v2/ to call, if it's not because that /v2/ will keep working independently of changes to the app. If it stops working some time because you're changing your app, you'll still have to inconvenience your users by pulling an old version out of production. On the other hand, there's no point in forcing users to upgrade to a "new" API, if the new API doesn't do anything the old one didn't.
No reason you couldn't just deprecate what will stop working on a method-by-method basis instead. If you pair it with application-keys, you'll know which users are using the methods you're about to deprecate and talk directly to them about transitioning away.
When something less radical changes, you can add new parameters and add new fields in the response just fine, without invalidating the old version - and if you can't, add a new method, e.g. /clients/list_with_invoices/ as the new version of list.
If you in the future decide to write the next version of your webservice using a different technology (e.g. going from python to node.js or whatever), you want your front-end server (e.g. nginx) to direct the traffic to the correct back-end without too much trouble.
Also, think about rolling-out backwards-incompatible changes otherwise. People want their apps to work immediately before you roll out the backwards-incompatible changes and immediately after. This means that for a period of time, you're going to have both up as they do the transition. (Your only other option is to say "at exactly 8:00 PST we're going to make the change. So deploy your changes that adapt to the change at exactly that time so you don't have downtime.) It's a lot cleaner to use versions and have them switch their urls from /v1/ to /v2/ whenever they feel like it. Otherwise, what are you going to do? You need api.yoursite.com to stay the old version so you don't break apps that haven't switched yet. So you'd have to do something ugly like have people switch to new.api.yoursite.com to get the newer version. Then, once you've disabled the old version and had api.yoursite.com, you have to get everyone to switch back to using api.yoursite.com because pretty soon, new.api.yoursite.com is going to be the following version. (Or you could make that version newer.api.yoursite.com, and then the next one newest.api.yoursite.com, and then you're really screwed when you need the next version.)
Basically, the cost of versioning your API is very low, and the potential headache of making backwards-incompatible changes without it is huge. Just do it.
GET /client
Accepts: application/vnd.clientlist.v1+json
And they would get back the version 1 client list response. If they want v2, etc, they can specify a different content type (clientlist.v2+json, etc). Also note, that putting verbs in your URIs is counterintuitive. The verb for a REST operation is the HTTP method (GET, POST, PUT, DELETE). The URI should simply represent the resource being retrieved. An argument can be made that the client list is the resource, but in reality listing things from a REST API is a first class concept and shouldn't need separate URIs. It's simply a request for a specific resource type without qualifying it by asking for a single instance of that resource. So, GET /client would return all clients (can add query parameters for pagination, etc), GET /client/834 would return a single client resource.
See also: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...
By doing it this way, you don't break links when you want to bump versions. Or if you have a single resource with an incompatibility, you can just upgrade the version of it, and leave all the others the same, without having to change anything, or your clients having to change theirs, either.
I wrote a blog post about this awhile back, please see point #4: http://blog.theamazingrando.com/your-web-service-might-not-b... (apologies for the formatting, I just imported it to Posterous, and it seems their styles aren't quite right)
Also, a former coworker of mine wrote a series of posts about this topic as well: http://barelyenough.org/blog/2008/05/versioning-rest-web-ser... http://barelyenough.org/blog/2008/05/versioning-rest-web-ser... http://barelyenough.org/blog/2008/05/resthttp-service-versio...
Also, how do you separate users accessing your API if not with X-* HTTP headers with an API key? (I'm referencing that link you posted). Would you not consider Gowalla (and hundreds of others who use X-* API key headers) as being RESTful?
Please do not place the version number in the URL, it is a horrible practice
In our case, we decided to go with the version number in the API (I don't think it matters if you use "1" or "v1"), because we wanted to be able to easily route requests to various API versions in the future (using load balancers). But it's more a matter of taste than a hard technical decision.
If there's no version... * If there request is plain html then deliver a human readable documentation page (that still has hyperlinks for discoverability. * If the request is asking for whatever your application type is, redirect to the current stable version.
If there's an older version requested: * If it's no big whup, keep the old version usable. Sometimes I do this by just keeping the old version of the resource code around, sometimes by updating it to translate between the old version and the latest stable version. * If you want to kill an old version, think about what appropriate in terms of 300 Multiple Choices, 301 Moved Permanently, or 410 Gone relative to your users.