How are REST APIs versioned?

I am currently working on a REST API, and the question was raised, how are, and how should, REST APIs be versioned? Here are the results of my research.

It seems that there are a number of people recommending using Content-Negotiation (the HTTP “Accept:” header) for API versioning. However, none of the big public REST APIs I have looked at seem to be using this approach. They almost exclusively put the API version number in the URI, with the odd exception using a custom HTTP header. I am at somewhat of a loss to explain this disconnect.

Versioning strategies in discussions

Post Versioning
Stack Overflow 1 URI
Stack Overflow 2 Content Negotiation
blog post by Jeremy Content Negotiation
ycombinator discussion some opinions both ways
Stack Overflow 3 Content Negotiation
Stack Overflow 4 Content Negotiation
notmessenger blog post URI (against all headers)
Peter Williams Content Negotiation (strongly against URIs)
Apigee Blog post on API versioning URI (some discussion)
Mark Nottingham REST versioning Recommending essentially versionless extensibility with a HATEOS approach
Nick Berardi on REST versioning URI
Restify “Accept-Version” header
Tom Maguire on REST versioning Content Negotiation
Nicholas Zakas on Rest Versioning URI
Steve Klabnik on Rest Versioning Content Negotiation + HATEOS
Luis Rei on Rest Versioning Content Negotiation with (;version=1.0)
kohana forum discussion on REST versioning Many Opinions
Troy Hunt on REST versioning Accept Header but also support custom header and URL
Paul Gear REST versioning Recommending essentially versionless extensibility with a HATEOS approach

Versioning strategies in popular REST APIs

API Name Versioning Example
Twillo date in URI
Twitter URI
Atlassian URI
Google Search URI
Github API URI/Media Type in v3 Intention is to remove versioning in favour of hypermedia – current application/vnd.github.v3
Azure Custom Header x-ms-version: 2011-08-18
Facebook URI/optional versioning
Bing Maps URI
Google maps unknown/strange
Netflix URI parameter
Salesforce URI with version introspection {
“label”:”Winter ’10”
Google data API (youtube/spreadsheets/others) URI parameter or custom header “GData-Version: X.0” or “v=X.0”
Flickr No versioning?
Digg URI
Delicious URI
LinkedIn URI
Foursquare URI
Freebase URI
paypal parameter &VERSION=XX.0
Twitpic URI
Etsy URI
Tropo URI
Tumblr URI
openstreetmap URI and response body http://server/api/0.6/changeset/create
Ebay URI (I think)
Reddit No versioning?
Groupon URI{.json|.xml}
Wikipedia no versioning I think?
Bitly URI
Disqus URI
Yammer URI /api/v1
Drop Box URI
Amazon Simple Queue Service (Soap) URI Parameter and WSDL URI &Version=2011-10-01
Youtube data API versioning URI

Versioning strategies in popular REST Libraries

Library Name Versioning Example
node-restify semver versioning in an accept-Version header accept-version: ~3
Jersey description of how to do Accept: header versioning in Jersey Accept: application/vnd.musicstore-v1+json