API Versioning

Hi Community,

I am working on API design for a customer but we seem to got stuck on versioning.

So far we have concentrated on the following options - note that I am not intending to document every single pros and cons here:

Version in URL:

https://api.company.com/v2/collection/id

Pros:

  • Asserts mandatory version number
  • Easy to use
    • Immediately visible
    • Browser friendly
  • Seems to be the most popular choice out there, google search, twitter, linkedin, etc.

Cons:

  • URI to represent the entity - not the version of the entity.
  • When version is changed, URI for the same resource changes.
  • If resource is being versioned - not the API, then version number seems to be in incorrect place in URL hierarchy.

Accept header (vendor extensions):

Accept: application/vnd.company.v2+json

Pros:

  • Seems to be the philosophical favourite
  • Allows resource level versioning

Cons:

  • Doesn’t seem to be used much by top API providers - perhaps I am missing it.
  • Doesn’t solve the problem if API behavior is changed, rather than the resource representation. Accept header in HTTP spec talks about media type/range. E.g. /collection1 returns a list of 50 resources. Now collection retrieval and filtering logic has to change and now it will return 100 resources - including new 50 that weren’t included in the results before. Server behavior is changed in such a way that response is not backwards compatible. Resource representation is still same - it is still v2.json.
  • Doesn’t assert mandatory versioning
  • Not easy to use:
    • Not immediately visible
    • Not browser friendly

Custom header:

X-API-Version: v2

Pros:

  • Handles representational and behavioral versioning needs
  • Seems to solve cons of other solutions - introduces new ones though
  • Allows resource level versioning

Cons:

  • Custom implementation and custom handling from consumers
  • Needs work to integrate into existing HTTP model, e.g. caching vary.
  • Doesn’t assert mandatory versioning
  • Not easy to use:
    • Not immediately visible
    • Not browser friendly

Item 2 overrides the meaning of the Accept header to include representation (media type/range) and behavioral versioning. Contrary to that, Item 3 introduces a whole new custom header.

I am interested to hear which option community is leaning towards. Which option are you using to version your APIs?

Cheers

2 6 4,490
6 REPLIES 6

Not applicable

A couple of minor points:

  • Mandatory versioning can be imposed using either of the headers, you can serve a 400 if the header is missing/malformed/incorrect.
  • If you are literally versioning the response then the accept is a pretty semantic way to do it but (as you mentioned) the content itself should not be affected, just the output format. This could also be applied to input formats content-type. If the intention is that the rules can change transparently but the representations (input and output) are versioned this is a good tool.

I am becoming more and more fond of versioning in the domain when it affects behaviour - your HTTP resources locations are the same regardless of the domain, therefore looking up https://v1.api.example.com/abc/def/ghi and getting a resource back which points to '/jkl/mno' allows you to look up https://v1.api.example.com/jkl/mno now but also address the same resource later at https://v2.api.example.com/jkl/mno. The SSL overhead is slightly higher but wildcard certificates would deal with that for you.

This solution makes it easy to see/manage/update and still browser compatible without it polluting the resource location itself.

Thanks Mat.

The point about "mandatory versioning" is that URL is the only place that implicitly asserts this. Headers and query parameters are not mandatory - apart from the Host header in HTTP/1.1 but even that isn't mandatory for 1.0. So by default headers and query parameters communicate "optional" to application developers. We would need to document a header/query param being mandatory in API documentation explicitly. On the other hand you can't make a request to the correct API/resource at all if URL is wrong. We can explicitly validate existing of headers/query params of course (as you mentioned) by rejecting it with 400.

Your comment about domains is very cool and we have customers opting for that option. SAN certificates are great for this for TLS. I just don't know how to apply this in microservices where each micro is versioned independently. Perhaps we would need to create a subdomain per each?

Not applicable

Ozan Seymen I read this book from Apigee few days back which has some tips on API versioning .

https://pages.apigee.com/ebook-web-api-design-registration.html

It talks about the 3 approaches you mentioned and few other examples like how twilio , facebook etc designed their APIs too.

akoo
New Member

Not to side-track this too much, but an important consideration is also whether to version all APIs or version domains of APIs (e.g., /v1/orders or /v1/customers). That's a question for a whole other post with pros/cons for each, but just bringing it up for your consideration.

Not applicable

Another good discussion if you should version or not. https://community.apigee.com/questions/21913/is-rest-apis-versioning-necessary.html

2 years ago i gave a presentation Slides about one of the ways we have done versioning