Measure Once, Cut Twice

Versioning REST APIs

Posted in REST by steve on July 2, 2010

There are three broad approaches to communicating version information:

In the URL

This is the most common approach. Simply add an identifier, usually near the root of the URL and version the entire set of resources below it (and hence the entire API).

This technique does a bulk versioning of the entire API and suggests that you shouldn’t mix resources across API versions. It is analogous to traditional API releases by sending out a new library versions. Bits within the old version (classes, data structures) are not intended to work smoothly with the new version. FWIW, this approach is common and well understood.

In the Media type

This seems to be the most RESTful to me, but hasn’t been widely deployed yet.

Content-type: text/vnd.mycompany.mytype+v1

There are other possible variations that change the scope of the versioning:

Content-type: text/vnd.mycompany.mytypesv1.sometype

It feels a bit awkward when using content type degradation conventions:

Content-type: text/vnd.mycompany.mytype+v1+xml

In general, the whole idea of extending mime-types to make them more flexible seems necessary but also limited. That little string simply can’t scale too far. What if you want to have a vendor specific type that also happens to follow some xml standard. Can you subsume that XML standards mime-type which may also have a +xml at the end?

In the Content

This is how the human driven web currently works. The content is returned with an un-versioned media type, usually from an un-versioned URL, and the handler of that media type needs to sniff the content to figure out what version was sent back. That is why we have HTML content declarations and a convoluted set of rules that are different for each browser on how to handle combinations of content declarations and browser versions (quirks mode!). In general, it works for the simple case but is difficult to manage when things get complex.

My preference right now is to define a small to medium number of media types and have them versioned independently of the resource space used to access them. Exceptions to this are when the media types are tightly related and are likely to all be consumed as a whole anyways. In this case, versioning the whole API offloads the dependency tracking from the consumer and guarantees them a complete, cohesive API. However, when this happens you should consider whether that coupling is truly necessary in the first place.