There are a few strategies for versioning a API, but let us get a step before, what happens in the project that requires a new version of the API?
Let's say we have a resource called Person, its contract includes id, name, birthDate, address, zipCode and city. At some point a decision is made to change it and separate the address information from the Person. It means that the contract will be changed because the address information will be moved to a separated resource.
All consumers will be broken, because they look at the address information inside the Person. This is a contract break. There are other cases where new information is added to the contract, which means it will not break any consumers, so we cannot consider this case as a contract break.
How to avoid breaking the consumers? Versioning it. At this point, API team will create a version 2 of the contract. Consumers will still use the old contract, however a version 2 of the contract will be published. Consumers and API team will now have an agreement on when the API will stop supporting the old version and consumers will have to start using the new version.
Versioning contracts looks like a good solution, but it can get dangerous if the API starts supporting a lot of versions. It will make your code look like a mess, hard to understand, too many branches on the code. I won't even mention that it can cause bugs (just did it :P). I'd say a good practice would be accumulating your contract breaks and release a new API version once you evaluate it is worth to. Also, I wouldn't have more than two vesions in parallel to avoid the issues mentioned above.
I've been researching a couple of solutions for API versioning, I will present and comment two strategies that most called my attention.
Version as path/query parameter
This is the strategy I've most seen on projects I worked on and on my researches. It consists in adding the version in the path like the example below:
Who is using this approach?
- Google Search
Version as a header
This is probably the less intrusive strategy, where the version is informed in the header Accept, leaving the URL clear. See the example below:
Accept: application/json; version=1.0
There are other ways to inform the version in the Accept header, but I thought this one is the clearer way. I also saw some example where people use a custom header like X-Version: 1.0
Who is using this approach?
- Github API
- Google Data API
A good contract design many times avoids contract breaks, which avoids versioning. Always be careful about the contracts, these set how the external world talk to your API. Contracts break, it's natural, however, always evaluate each change, think about your design and ask yourself if each change is really the right thing to do, collect the pros and cons and do smart decisions.