

Version your RESTful API responses - yuxt
http://hribar.info/2012/09/version-your-api-responses/

======
bryanh
The whole point of a REST API version bump is that it is an artifact of
introducing necessary breaking changes (either removing an endpoint at X path,
removing Y keys, or even serializing dates in Z format).

Though there have been many detractors, I still think URL based versioning is
the best way to go. How do you version a header on a resource that goes away
or pops into existence? What if I just ask for "application/json" or the
"freshest" due to ignorance and you move the target and get even fresher?
There is very little practical benefit to versioning in a HTTP header except
some argument about URI purity.

~~~
ldh
If you're writing a client which is sensitive to the resource representation
changing over time and you're using something that calls itself an API,
hopefully one would skim the provided docs enough to see that you might want
to explicitly state the version you want. Or notice that the Content-Type
returned for the generic application/json query is a versioned type.

I acknowledge that it's a little more work than just banging out a versioned
URI, but it's not that much work and I like the URI/conceptual purity.

~~~
zimbatm
> and I like the URI/conceptual purity.

This sums up pretty much the whole debate. Pragmatics vs idealists.

~~~
j_s
The interesting thing is that it is a false dichotomy - it's easy enough to
implement both. Perhaps enhanced by adding a flag on the documentation to flip
between pragmatist/idealist so each only sees their one way to do it right...

------
terryjsmith
While this seems like a good solution, I'm not sure the problem is real: to
me, a v1 API and a v2 API are two separate APIs, so the URLs for that API
aren't really changing during it's lifetime (ie. the v1 stuff will stay the
same for those continuing to use it). I think this is just a mis-
interpretation of a core REST/web principle that the URIs for a specific
resource in the API shouldn't change (hence creating a v2 or other sub-
directory if you're going to change the output or functionality).

~~~
optymizer
Ok, therefore:

    
    
      GET / HTTP/1.0
      GET / HTTP/1.1
    

should be

    
    
      GET /v1
      GET /v2
    

and YOU'd have to tell the browser which site uses which version.

Wouldn't it be nicer if the browser could tell the server which version of the
interface it understands?

It happens that the metadatum follows the URI in HTTP requests. The author
can't do that, but he can use a header field to achieve the same.

Hence the idea to use "Accept:" for versioning.

~~~
zimbatm
That's not the same layer. HTTP versioning is on the transport level.

All that the author is going to achieve is to have broken client codes every
time he's going to bump his API version because most developers won't bother
to check the content-type. Or he has control of both the client and server
code and then in that case it doesn't matter.

~~~
optymizer
N.B.: yes it's the same layer. HTTP is at the Application layer in the
Internet layer model (and this is the Internet, not your school's Network
class where they dream about OSI layers).

It's irrelevant which layer this is happening at. The point is that there is a
resource address and a resource version. Decoupling those allows you to retain
the same resource address for different resource versions - whether this is
done for backwards compatibility, multi-language support or other reasons.

"All that the author is going to achieve is to have broken client codes every
time he's going to bump his API version because most developers won't bother
to check the content-type."

The point of the article was in fact to teach those mediocre developers who
"won't bother", to actually bother to understand these concepts.

------
zimbatm
How often do you update the major version of your API ? Most of the time you
can just augment your API with new end-points and keep the old paths around
for backward-compatibility. When you're ready to change the major version you
might as well start a new service from scratch with everything that you have
learned.

Now that all your responses have a non IANA-approved[1] content-type, standard
clients won't see it as JSON by default. Your curl requests are longer to type
because you have to add this '-HAccept:application/vnd.something+json' string
to your them. The reality is that bad developers will have broken clients when
you update your API in any case.

I'm grateful that the REST movement brought attention to follow the HTTP
protocol more closely but in practice, nobody writes truly RESTful clients.
For that you would need to write a client that follows URLs passed in the body
or in the headers. For example if you implement pagination, you're supposed to
fetch page 1 and then follow the links until you're at the page you want. In
reality you just make a page= attribute convention that avoids all these
unnecessary round-trips.

[1]: <http://www.iana.org/assignments/media-types/index.html>

------
urbanautomaton
I personally prefer this approach - certainly if the changes you're making are
only to the representation of your resources, then (assuming they can't be
made purely additively, i.e. without breaking existing clients) simply making
a new content type available seems the natural way to go.

If it's of interest, I wrote a couple of articles about how we implemented
exactly this sort of versioning in Rails for our app's API:

[http://techblog.tribesports.com/blog/2011/09/24/versioning-t...](http://techblog.tribesports.com/blog/2011/09/24/versioning-
the-tribesports-api)
[http://techblog.tribesports.com/blog/2011/09/24/separating-a...](http://techblog.tribesports.com/blog/2011/09/24/separating-
api-logic-with-decorators)

I think these demonstrate the advantages of content negotiation as a
versioning mechanism. To introduce a new API representation, we simply have to
define a new set of decorators for our exposed resources, define a new MIME
type and we're set. No monkeying with our routing, no messing around in
controllers; a view-level change entails only view-level code alterations.

------
candybar
I don't hate the idea or anything but I don't see what problem this solves in
practice?

~~~
13rules
Agree ... normally the V2 API comes out with major revisions, such that it
would not work with someone that coded up an app based on the V1 API. Using
/v1/ and /v2/ allows customers to transition over some set amount of time.
There is some value in keeping things simple for your end-users.

~~~
ajanuary
If the customers use 'Accept: application/vnd.example.v1+json' and 'Accept:
application/vnd.example.v2+json' they can also transition over in the same
manner.

------
bluetidepro
I like this idea a lot! I'm curious if anyone else finds major flaws in this
idea but it seems to make a lot of sense to me. Yes, it may change slightly
how you do your calls, but if the logic works and that's the "worse thing"
that could come from this then I think it's worth implementing.

~~~
awj
* You cannot test this from the browser.

* Many, many client developers will be confused by this approach. Also if they're using a shitty http library (often, yes) they'll hate you.

* What happens when someone sends an "Accept: application/json"? If you default to "send the latest" developers will fail to read your docs and get pissed when your next version breaks their code.

* His citation of Fielding's dissertation at best fails to support his claim and at worst is a misunderstanding of it. How is "put this in your accept header" any more of a uniform interface than "this thing goes in urls"? If you're doing HATEOAS[1] properly the answer is: "accept headers are _less_ general and thus worse". If you include api versions as a fundamental part of the notion of a resource they seem to become important enough to need top level (e.g. URI) support.

All in all this seems like a thinly veiled argument for URI purity for its own
sake. API versions change the definitions of what a resource looks like _and_
what you can do with it. What more is there to a resource? What benefits,
aside from sweeping the versioning mess under the header rug, does this
provide?

[1] <http://en.wikipedia.org/wiki/HATEOAS>

~~~
regularfry
URIs should be black boxes. My understanding is that the client should need no
understanding _at all_ of their content.

~~~
awj
I agree. This is only possible when all resource access flows from a
predefined "root" resource via hyperlinks. If you're doing that, why force
(arguably more difficult) accept header handling on your api clients? Then
they have to set the accept header correctly at _every_ request instead of
getting the version number right once when retrieving the root document.
Beyond that debugging now requires access to / a record of the accept headers
involved, and returning the latest version for plain application/json creates
a _very_ nasty bug for clients.

I don't think REST meaningfully comes down on either side of this idea. I do
think practicality sits highly in favor of versions in URIs.

~~~
ldh
Setting the same Accept header at every request is _not_ difficult or error-
prone.

But that aside, what happens when you store versioned resource URLs in the
client, and then you want to upgrade your client to a new version of the API?
Do you just lose all of your data from the old version, since you don't have a
single URL for a resource?

------
pbreit
With just a bit of forethought and a little planning, an API almost never
really needs to be versioned in either way. One of the problems with
versioning is that it almost encourages changing the API and most consumers
are slow to update, if at all.

