Overview#API versioning is the methodology of naming and deploying Application Programing Interface versions.
What you are creating is not a new version of the API, but a new system with a new brand. On the Web, we call that a new website. Websites don’t come with version numbers attached because they never need to. Neither should a RESTful API. A RESTful API is just a website for clients with a limited vocabulary.
— Roy Fielding
The various versioning camps#Right, so how hard can this versioning business be? I mean it should be a simple exercise, right? The problem is that it gets very philosophical, but rather than get bogged down in that for now, let me outline the three common schools of thought in terms of how they’re practically implemented:
- URL: You simply whack the API version into the URL, for example: https://willeke.com/api/app1/v2.1/method1/1234
- Custom request header: You use the same URL as before but add a header such as "api-version: 2"
- Accept header: You modify the accept header to specify the version, for example “Accept: application/willeke.com.app1+json;version=2.1”,“application/json; profile=application/willeke.com.app1 version=2.1"
There have been many, many things written on this and I’m going to link to them at the end of the post, but here’s the abridged version:
- URLs suck because they should represent the entity: I actually kinda agree with this insofar as the entity I’m retrieving is a breached account, not a version of the breached account. Semantically, it’s not really correct but damn it’s easy to use!
- Custom request headers suck because it’s not really a semantic way of describing the resource: The HTTP spec gives us a means of requesting the nature we’d like the resource represented in by way of the accept header, why reproduce this?
- Accept headers suck because they’re harder to test: I can no longer just give someone a URL and say “Here, click this”, rather they have to carefully construct the request and configure the accept header appropriately.
Best Practices for API versioning#Our suggestion is that you keep the url to the API consistent and that it represent the "current" version.
We also suggest the Accept header contain the with the current version and document in APIs use Content negotiation. This will permit consistent access the your APIs without changing their applications. Clients should perform Content negotiation as required.
Accept header Example to:
GET /api/app1/ HTTP/1.1 Accept: application/willeke.com.app1+json;version=2.1”,“application/json; profile=application/willeke.com.app1 version=2.1"
You might also make versions available via versioned URLs
https://willeke.com/api/app1/v2.1/method1/1234 https://willeke.com/api/app1/v2.0/method1/1234 https://willeke.com/api/app1/v2/method1/1234 https://willeke.com/api/app1/v1.1/method1/1234 https://willeke.com/api/app1/v1/method1/1234
- 301 Moved permanently indicating that the resource with a requested URI is moved permanently to another URI (which should be a resource instance permalink that does not contain API version info). This status code can be used to indicate an obsolete/unsupported API version, informing API client that a versioned resource URI been replaced by a resource permalink.
- 302 Found indicating that the requested resource temporarily is located at another location, while requested URI may still supported. This status code may be useful when the version-less URIs are temporarily unavailable and that a request should be repeated using the redirection address (e.g. pointing to the URI with APi version embedded) and we want to tell clients to keep using it (i.e. the permalinks).
- other scenarios can be found in Redirection 3xx chapter of HTTP 1.1 specification