
Ask HN: Version numbers in a REST API - qixxiq
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).<p>Obviously the latter is far cleaner and simpler, but am I shooting myself in the foot by leaving out the version number?
======
defeated
Actually, I think best practice is to not put the version number in the URI at
all. Instead versioning should be handled via content negotiation. That is to
say, a client specifies the type of resource they want back via the Accepts:
header, and that resource is versioned. So A request would look something
like:

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...](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-
driven)

~~~
psadauskas
Can I have a few more upvotes please? This is the only way to do it. There's
currently two root posts above this one advocating the incorrect way, with
versions in the URL.

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...](http://blog.theamazingrando.com/your-web-service-might-not-be-
restful-if) (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-services/)
[http://barelyenough.org/blog/2008/05/versioning-rest-web-
ser...](http://barelyenough.org/blog/2008/05/versioning-rest-web-services-
tricks-and-tips/) [http://barelyenough.org/blog/2008/05/resthttp-service-
versio...](http://barelyenough.org/blog/2008/05/resthttp-service-versioning-
reponse-to-jean-jacques-dubray/)

~~~
killedbydeath
Isn't the point of bumping version to signal incompatible API changes? In that
case breaking links is probably a better solution.

------
mitchellh
Please namespace your URLs by a version, such as "v1" (not just "1", which
looks like a resource ID). If anything, this will motivate you even more to
maintain backwards compatibility when you update your API, since there is
nothing more infuriating to a developer than waking up one day to find an API
call has changed (I'm looking at you Facebook).

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.

~~~
psadauskas
No, this is incorrect. If you have versions in your url, then the same client
(eg, with ID 1) has two resource identifiers, /v1/clients/1 and /v2/clients/1.
In fact, you have the same resource, /clients/1, but multiple versions of the
_representation_. There's links further down, the one by Peter Williams in
particular, that describes a way to do this using content negotiation and the
Accept header.

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.

~~~
epochwolf
> 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.

------
rmoriz
There are many ways to do it.

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)

~~~
reynolds
I can't recall a single API I've seen or used that took the academic approach
of using HTTP Accept headers. All of the major REST APIs I've seen have used
API key X-* headers and most of them use versioned URIs.

It seems there are two REST camps: academics and those who actually write
real-world APIs.

~~~
technoweenie
<http://api.tenderapp.com>. Course, I didn't work on it long enough to need
another version :) I think I messed up by using a single version for the whole
API. I think it makes more sense to have a versioned mime type for each
resource (if that's how you choose to roll).

------
vyrotek
We also just had to research this as well for our API. Our solution is based
on this - [http://stackoverflow.com/questions/389169/best-practices-
for...](http://stackoverflow.com/questions/389169/best-practices-for-api-
versioning)

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.

~~~
jackowayed
I'm not sure how I feel about that. Then you're going to be ok with making
backwards-incompatible changes, but a lot of people may change to them
immediately because they're not using the versioned url.

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.

~~~
vyrotek
You're right, but this is the side effect of 'releasing early' and responding
to custom feedback. You're usually safe to make drastic changes when its just
the web application but APIs are a different story. The world of APIs is about
stability and backwards compatibility, but sometimes this just isn't possible.
If you remove a feature or drastically change how something behaves then it
isn't possible to make it backwards compatible. If it is a drastic enough
change then even the version numbers won't save you. Perhaps you completely
changed how some data is persisted or queried. Its really hard to justify
keeping old/broken things around when you probably just wrote and released
that a month ago and now you've taken a different approach.

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.

------
Sujan
Uh, difficult topic.

I 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://blog.sonoasystems.com/detail/one_size_doesnt_fit_all_api_versioning_and_mediation/)
[http://stackoverflow.com/questions/389169/best-practices-
for...](http://stackoverflow.com/questions/389169/best-practices-for-api-
versioning) [http://stackoverflow.com/questions/2024600/rest-api-
versioni...](http://stackoverflow.com/questions/2024600/rest-api-versioning-
only-version-the-representation-not-the-resource-itself)
[http://stackoverflow.com/questions/972226/how-to-version-
res...](http://stackoverflow.com/questions/972226/how-to-version-rest-uris)
[http://stackoverflow.com/questions/278686/versioning-
restful...](http://stackoverflow.com/questions/278686/versioning-restful-
services) [http://stackoverflow.com/questions/1679322/web-services-
api-...](http://stackoverflow.com/questions/1679322/web-services-api-
versioning) [http://stackoverflow.com/questions/2101566/what-are-your-
web...](http://stackoverflow.com/questions/2101566/what-are-your-webservice-
versioning-best-practices) [http://barelyenough.org/blog/2008/05/versioning-
rest-web-ser...](http://barelyenough.org/blog/2008/05/versioning-rest-web-
services/)

Examples:
[http://docs.amazonwebservices.com/AWSEC2/latest/APIReference...](http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?api-
versioning.html)
[http://atlas.resources.ca.gov/ArcGIS/SDK/REST/versioning.htm...](http://atlas.resources.ca.gov/ArcGIS/SDK/REST/versioning.html)
[http://groups.google.com/group/twitter-api-
announce/browse_t...](http://groups.google.com/group/twitter-api-
announce/browse_thread/thread/2b70bd6ea4aec175?pli=1)

Hope this helps a little bit.

~~~
qixxiq
Wow, I guess I got to work on my research skills a bit more.

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')

~~~
the-kenny
What would be the problem of including a number? one more (static) segment in
the url. Just do it, if it makes (or will make) your life easier.

However, I would name them "v1", "v2" etc. That makes the purpose of the
number clear.

------
mseebach
Hmm.. I don't really see the need for versioning in REST APIs. Webapps don't
have versions, because it's smarter to just push small changes continuously.
Your API maps functions in this changing application - keeping an old API
around isn't like keeping an old version of Word around. If the app changes so
a given API call won't work any more, it won't magically keep working because
of versioning...

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.

~~~
prototype56
Yea having to version a "REST"ful api usually means its a was not very restful
in the first place . Meaning the api is not hypertext driven and is probably a
rpc style api with meaningful urls. If it was hypertext driven it would all be
transparent to the consumers , it could be v2 or foobar , doesn't matter .

------
berryg
I like the approach that Peter Williams has suggested. That is to use a vendor
MIME media type in the Accept header to specify a required API version. At
least your URL stays the same. As it should be, because your resource is still
the same.

[http://barelyenough.org/blog/2008/05/versioning-rest-web-
ser...](http://barelyenough.org/blog/2008/05/versioning-rest-web-services/)

------
Qix
How about putting the version number in the hostname?

<https://api-v1.xxxy.com/clients/list>

I believe its a little neater than /v1/clients/list, albeit a little less
standard.

------
shib71
You should incorporate the API version.

    
    
      - you're developing a service would typically be a core part of your client's businesses
      - the API will almost certainly need be revised after you release it
      - even if you choose not to support deprecated versions, you will need to give your clients enough time to switch
      - that means that there will be periods where at least two versions of the API will be live
      - and both versions will need to be live on their final endpoints

------
jackowayed
Definitely do it. Having the "/v1/" (I agree with the comments that the v is
better.) is still plenty "clean". No one is going to say "well, I was going to
write an awesome app with their API, but those 3 extra characters to make sure
my app doesn't break made it too much of a pain."

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.

------
dan_manges
If you're not sure how you want to do this, you could always wait until you
need to implement version 2. You would then be forced to have omission of a
version number indicate version 1, but waiting would allow you to make the
decision when you're actually ready to begin implementation and might have a
better idea or more information about how you want to approach it.

------
johnm
Use versions like /v1/ .

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.

------
jmillikin
Just put a version number in the API root -- it really doesn't matter where.
<http://api.mysite.com/1/> , <http://api.mysite.com/?version=1> , etc,
anything will work. In fact, you can support multiple styles easily.

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.

------
jwr
I had the same problem when designing a REST API a while ago. After reading
lots of documents on REST philosophy I decided that no one _really_ knows what
REST is and there is no precise answer.

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.

------
warp
Make sure you can easily route requests for a particular version to a
different back-end server.

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.

------
joubert
See this conversation on SO: [http://stackoverflow.com/questions/2024600/rest-
api-versioni...](http://stackoverflow.com/questions/2024600/rest-api-
versioning-only-version-the-representation-not-the-resource-itself)

------
yason
How about /version that your client can GET and see which is
expected/required/supported?

------
rix0r
You can also negotiate the version number in the HTTP header:

    
    
      X-protocol-version: 3
    

That way you don't need to pollute the address space.

~~~
Qix
Maybe, but what do I do if the header is missing? Use the latest version?

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.

~~~
dazzawazza
personally I would put the API version as an argument to the URL and I would
make it a requirement. Most developers likes strict requirements, no developer
likes surprises either.

/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.

~~~
mahmud
The #1 danger to your API's usability is the half-assed implementation a 3rd-
party will release to the public without your prompting or involvement. Don't
let that happen. Take initiative and release libraries for as many languages
and frameworks as you can, or risk the danger of being sabotaged by someone's
indifference, or most likely incompetence.

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.

------
srepetti
You can also embed the version number in the API call itself, using a default
if not passed or auto detecting based on what is passed.

