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,570