Versioning Your API
Choosing an API versioning strategy can be difficult. There are many approaches and
each come with their own pros and cons. Two of the most common practices are to version
in the URL or with headers. For Heroku’s public API we decided to version with the
URL Versioning is Dead Simple
If you’re not familiar with URL versioning it’s simply having the version number as
part of the URI, for instance,
example.com/v2/resources. This approach is very clear
and easy to call in code or at the command-line. The problem I see with URL versioning
is that it’s not forgiving. If/when the version is no longer available the server will
Accept Header Versioning is Forgiving
To version with the
Accept header the API has to listen for a custom media type and
respond accordingly. Github chose the media type
3 is the API version. For Heroku’s API we decided on
application/vnd.heroku+json; version=3, also where
3 is our version of the API.
In section 14.1 of the HTTP Spec the document indicates that multiple media types
can be passed in the
Accept header. If the first media type requested isn’t available
the next type can be returned and it continues down the line. If the following
header is sent to an endpoint that does not have a version 3 response it will disregard
the Heroku media type and return the default response as JSON.
Accept: application/vnd.heroku+json; version=3, application/json
I prefer this approach over URL versioning because of the ability to set multiple types in one request.
Understanding a Custom Media Type
A media type consists of two or more parts—type, subtype, and optional parameters.
The Media Type Spec states the
application type is meant for content that is
to be processed by applications before being viewed or usable by a user. That
sounds perfect for an API.
Sub types that begin with
vnd are vendor specific media types. These media types
are defined and controlled by the vendor. Creation of and modifications to vendor
media types aren’t subject to community reviews.
+json indicates that the content is a JSON structure. This is key to custom
media types, whether a vendor type or experimental (prefixed with
it shows how the data should be parsed once received.
Lastly, parameters allow for additional information to be passed without changing the
media type. A
version parameter can be used to support multiple API versions during
a transition period.
In the case of Heroku’s API we will respond to
application/json by default and
application/vnd.heroku+json; version=2 and
upon request. The default response will render the same as
until version 3 is completed and widely adopted. At that point the default
application/json response will render the same as
vnd.heroku+json; version=3 and
version 2 will be available through the custom media type.