Thursday, February 02, 2012

Versioning RESTful APIs

There seems to be general (but definitely not complete) consensus among REST experts that the proper way to version a REST API is via custom MIME/media types.  You can Google this for yourself to find the discussions on the rest-discuss mailing list, Stack Overflow, various blogs, etc.

There was one subtlety to the discussion that I found interesting and I spent some time researching.  Most folks propose media types like:


However a few folks, based on examples in the section of the HTTP spec for the Accept header, suggest a format like:

"application/vnd.mycompany.myapp+xml; level=2"

That's often countered with the argument that an "accept-extension" like "level" is optional (with the implication that it can be ignored if present, which seems like an unfounded assumption), or that it should only be used to indicate minor versions.

However my reading of the examples in the HTTP spec and related historical documents leads me to believe that using "level" to indicate major versions was exactly the intended purpose. All usage of the "level" extension historically seems to have been in relation to the “text/html” MIME type, and specifically to indicate major versions of the HTML spec (HTML 2, HTML 3, etc.) This page ( dated 1995 clearly shows usage of a "text/html; level=3" media type to indicate to HTML 2 only clients that they won’t understand the markup and should not attempt to do so.

That said, this is largely an academic exercise. In the absence of specific definition it seems like media types must be treated as opaque strings, so "application/vnd.mycompany.myapp-v2+xml" and "application/vnd.mycompany.myapp+xml; level=2" both serve the same purpose. Since there seems to be consensus that the former is the better format to use I’ll be going that way, I just don’t see any reason that the later format is any less valid. And in fact using the "level" extension for minor versioning seems counter to historical precedent, but (IMHO) acceptable and harmless if used on a custom MIME time.