HOW TO (NOT) VERSION YOUR API
Michael Pratt
I'm Mike
Developer Evangelist
Platform Engineer
Bazaarvoice
@urthen
urthen@gmail.com
urthen.com
What this is not!
- Step by step guide to creating a versioned api in {{your_language}}
- Statement of a well-defined standard
- Recommendation for every API you want to build
- Strongly held personal belief of which your disagreement will cause me severe emotional pain
Not a declaration that if you do these things you are bad and your API is bad
I'm sure your API is fine.
What this is
- Thoughts on the conscientious design of the web
- Pros and cons of various versioning strategies
- Strategies for architecting a version-less API, if appropriate
- Ideas for future development
Why version your API?
One overwhelming reason:
Prevent breaking client applications
- Clients have control over their own upgrades
- Versions can be deprecated on a schedule
A segue about URIs
Universal Resource Indicator (Superset of URLs)
Indicates a resource, not a representation thereof
Should always indicate the same resource
Assume different URIs may indicate different resources
What makes a "good" URI
These would probably be bad:
http://www.example.com/ponies/zomg/yay.json.php.actually_its_xml http://www.example.com/7 http://www.example.com/api/C394235458E3E32A157C7AC2956DA
But they are all valid. To enhance developer joy and adoption, we make nice URIs:
http://www.example.com/api/bars/1
This has nothing to do with compliance nor does it define a RESTful API.
Versioning your API
Changing Hostnames
http://www.example.com/api
to:
http://newapi.example.com/
PROS:
Effectively same as just creating a new API
Can completely change URI structure
Can leave entire previous API stack untouched until deprecated
Cons:
Expensive to leave previous stack up
Clients may need to change security settings
Adding version to URI Template
http://www.example.com/api/v1/foo
to:
http://www.example.com/api/v2/foo
or
http://www.example.com/api/foo
to:
http://www.example.com/api_v2/foo
Pros:
Most widely used and understood method
Easy to implement from the beginning
Can change entire path after version indicator
Deprecated versions can (optionally) be redirected to latest version
Cons:
Clutters URI template with representational information
Often achieved internally with code duplication
Adding version to query parameters
http://www.example.com/api/foo?apiVersion=1
to
http://www.example.com/api/foo?apiVersion=2
Pros:
Easy to make optional, if desired
Not part of the URI path
Cons:
Cannot easily change URI templates
Passing a custom header
Accept-version: 1; GET http://www.example.com/api/foo
to:
Accept-version: 2; GET http://www.example.com/api/foo
Pros:
Easy to make optional
Not cluttering URI or query parameters.
Easy to ignore or optionally upgrade deprecated versions
Cons:
Technically Accepts-Version is not a real header
Unclear on whether API itself or resource representation is versioned
Cannot easily change URI templates
Can be harder to specify during testing
Accept Header Parameter
Accept Header is Complicated
The spec is pretty hard to comprehend.
Everyone knows this:
application/json
text/html
But who didn't know you can specify this:
application/vnd.example.foo+json;version=1
application/vnd.example.foo_v1+json
Pros:
Fits within standards and conventions
Clearly versions only the individual resource representation
Clients can accept multiple versions
Easy to ignore or silently upgrade
Cons:
Proper accepts header parsing support is hard to find
Slightly more complicated to specify than a simple Accept-version header
Cannot change URI templates
So how/when do I version my API?
If you're not 100% certain of the future design of the API,
at least have a versioning strategy
Semantic versioning is your friend!
Only increment api version on major (backwards-incompatible) versions.
Think before duplicating code.
Or, you could.... not.
Ever.
(seriously)

HOW TO NOT VERSION YOUR API
Caveats:
Not every API architectures can be versionless
Going versionless is more difficult than versioned
More or less requires Hypermedia
Most APIs, however, can be architected in a versionless fashion.
Versionless Interfaces
URI templates define the paths to resources.
Resources have a few states of being in the HTTP world:
Here it is (200)
It's somewhere else (301, 302, 303, 307)
It was here, but it's gone forever (410)
Nothing was ever here (404)
Resources can exist, or not
Resources can always be added
Don't remove resources without a business reason.
Resources can be moved with redirect codes
Have well-defined methods
Follow HTTP Verb standards:
-
GET retrieves resources.
-
POST accepts entities but does not specify what to do.
-
PUT accepts entities and stores them at the requested URI.
-
PATCH accepts partial entities to edit existing resources.
-
DELETE deletes the resource at requested URI.
Be very careful with POST!
Use future-proofed URI templates
Good:
http://www.example.com/api/bars/1
or, generically:
http://hostname/api_name/resource_name/id(/subresources?)
Bad:
http://www.example.com/api/bars.json
http://www.example.com/api/addNewBar
http://www.example.com/api/getBar?id=1
Versioned Representations
Resources can, and will change.
Adding information should be backwards-compatible
Removing information should be done in every version
Moving or altering information semantics must be versioned
Separate Versioning
Specify version in headers
Content negotiation is your friend!
Each resource can have separate versions
So, how do I do this?
Unfortunately, library support for API versioning is sparse
Which is silly, because most APIs do it.
Tips
Think before duplicating code
Find libraries that support versioning
Try versioning your representations themselves
Model/Adapter architecture
Ideas
Build versioning support into libraries!
These strategies aren't used because they aren't easy
(make them easy)
Promote standards!
Thanks!

HOW TO (NOT) VERSION YOUR API
By Michael Pratt
HOW TO (NOT) VERSION YOUR API
Detailing methods to version your API, and thoughts you can keep in mind to architect a version-less API.
- 4,428