One of the most frequent questions I receive during API training and coaching engagements involves versioning. When to version. How to version. Whether to version at all. While not all APIs are exactly the same, I have found that there are certain patterns and practices that work for most team. I have pulled these together to provide a recommendation for a versioning strategy that will help most API providers – whether they are deploying internal, private APIs or public APIs outside the organization.
Do you really need to version your API?
APIs are contracts established between you and your API consumers. Ideally, you will never have to break this contract. This includes URI patterns, payload structures, field and parameter names, expected behavior, and everything else in between. The biggest benefit of this approach is obvious: An API consumer’s understanding never expires. Applications continue to work, making your consumers happy.
However, that may not be reality. There may be times when you need to make a breaking change. When this happens, you need to ensure that you never do anything that will cause your API consumers to fix code.
Breaking vs. non-breaking changes
Non-breaking changes tend to be additive: adding new fields or nested resources to your resource representations, adding new endpoints such as a
PATCH that was previously unavailable. API consumers should build client code that is resilient to these kinds of non-breaking changes.
Breaking changes include:
- Renaming fields and/or resource paths – often for clarity after your API is released
- Changing payload structures to accommodate the following: renaming or removing fields (even if they are considered optional – contracts!); changing fields from a single value to a one-to-many relationship (e.g. moving from one email address per account to a list of email addresses for an account)
- Fixing poor choices of HTTP verbs, response codes, or inconsistent design across your API endpoints
In short, once you release your API into the wild, you have to live with it. If you encounter one or more of the items above, it may be time to version your API to prevent breaking your existing API consumers.
Defining Your API versioning strategy
Any evolving, growing API will require an API versioning strategy. When and how you version may vary based on the expectations of your API consumers. I generally recommend the following API versioning strategy as part of an overall API governance model:
- If your API is in an early preview release, perhaps to gain feedback from consumers, establish proper expectations that your API may change. At this stage, you will remain at version 1 for some time but your API design may change. Things are volatile as a consumer, so they should expect that changes may occur
- Once released, your API should be considered a contract and cannot be broken without a new version release
- API versions are major.minor, following the general principles of semantic versioning
- Non-breaking changes result in a bump in the minor version; clients are automatically migrated to the latest verison and should not experience any negative side-effects
- Breaking changes result in a new major version; clients must specifically migrate to this new version as it contains one or more breaking changes. You must establish an appropriate timeline and regular communication with your API consumers to ensure that they migrate to the new version. In some cases, this may not be possible and your team will be required to support the previous API version indefinitely
How to implement API versioning
Once you determine that you need a new version of your API, you need to decide how to handle it. Preferrably, you have decided ahead of time and encouraged API consumers to request version 1 of your API. There are three common approaches to implement API versioning:
- Resource versioning: the version is part of the Accept header in the HTTP request. e.g.
Accept: application/vnd.github.v3+jsonis sent to
GET /customers. This considered the preferred form of versioning by many, as the resource representations are versioned while keeping resource URIs the same. Some APIs choose to provide the latest version as the default, if not provided in the Accept header
- URI versioning: the version is part of the URI, either as a prefix or suffix. e.g.
/customers/v1. While URI-versioning isn’t as pure as content-based versioning, it tends to be the most common as it works across a variety of tools that may not support customized headers. The downside is that resource URIs change with each new version, which some consider counter to the intent of having a URI that never changes.
- Hostname versioning: the version is part of the hostname rather than the URI. e.g.
https://v2.api.myapp.com/customers. This approach is used when technology limitations prevent routing to the proper backend version of the API based on the URI or Accept header.
No matter which option you choose, API versions should only include the major number. Minor numbers should not be required (e.g.
Remember, APIs are contracts with your consumers. Break your contract and a new version is required. Choose a strategy, have a plan, and communicate that plan with your API consumers. They will thank you for it.