To grow a user base and build out an integration ecosystem around your application, you need to foster trust with the developers who leverage your API. The best integrations rely on stable APIs — in other words, APIs that very rarely change how clients use them.
But, what would make an API unstable? Often, it’s something as simple as a planned update. Changing even one small aspect of your API may break client applications, hurting their business and damaging the trust they had with your service.
Still, change is unavoidable, which is why we have API versioning. With a clear API versioning strategy, you can make improvements to your API that draw in new users without affecting existing consumers.
In this post, we’ll introduce the concept of API versioning, why it’s important, and when (and when not) to version an API. We’ll also review common methods for labeling API versions in client requests. I’ll be basing this post around REST APIs since they’re the most common type used in web-based applications.
What is API versioning?
API versioning is the practice of managing changes to an API and ensuring that these changes are made without disrupting clients. A good API versioning strategy clearly communicates the changes made and allows API consumers to decide when to upgrade to the latest version at their own pace.
Why API Versioning Is Important
At its core, an API is a piece of software. And like all software, APIs need to update every once in a while.
However, unlike other software you might use regularly, even seemingly minor updates to an API can result in downstream effects that cause significant problems for users.
Consider a piece of consumer software, like HubSpot. We introduce updates to our tools all the time to fix bugs and add new features we think customers will like. When a new feature is added, it usually doesn’t disrupt the average customer. A user probably doesn’t need to drop everything in order to adapt to this change.
This isn’t the case with APIs. When a third-party application developer uses your API to build an integration, they expect that the API will be stable. If you make changes to your API without considering clients, it forces them to change their own software. Otherwise, their applications could break if updates aren’t accounted for.
But, of course, the truth is you can’t expect all your API consumers to drop everything when updates occur. People have other things to worry about, and requiring them to turn their attention to your integration will cost them time and money.
This is why API versioning is about more than simply changing the version number of an API. It’s about avoiding major updates whenever possible and, when these updates do occur, clearly communicating them to customers in announcements via the website, email, and documentation.
Crucially, versioning also means preserving previous versions of your API so that client integrations remain functional, even if they can’t upgrade to your latest API version just yet. This allows developers to improve the API without breaking client applications and losing users.
When to Version an API
Because API versioning is costly for both API consumers and developers, it’s considered a best practice to version your API only in the event of a breaking change. A breaking change is any change to your API that may cause client applications to fail. Breaking changes require the API consumer to rewrite their software to avoid problems.
Breaking changes are obviously not a great experience for your consumers — you’re placing the burden on them to adapt to your changing technologies. Their product depends on your product (the API), and by making big updates (and failing to communicate them), you’re breaking trust.
So, you should refrain from making breaking changes and versioning whenever possible. However, they’re sometimes inevitable. A breaking change could be:
- Changing the format of request or response data (like switching from JSON format to XML format)
- Changing the data type of a resource (like changing from a string to an integer)
- Changing the name of a resource
- Removing one or more resources, removing or changing properties or methods for a particular resource, or any other changes to API functionality
- Adding a new required field for client HTTP requests.
These changes, if unavoidable, warrant a new API version.
When Not to Version an API
Avoid versioning your API in the event of non-breaking changes. If there’s a way to update the existing version of your API in such a way that consumers can choose to embrace or ignore the update, then you should do that. You could also include non-breaking changes in a new API version along with more major updates, but they don’t warrant versioning on their own.
For example, a non-breaking change could be adding new methods (e.g., PUT, POST) for a resource, or adding new resources and endpoints. In the latter case, you can add resources without changing existing endpoints. This ensures that existing integrations won’t break, since they can just continue to use existing endpoints and adopt the new endpoints if desired.
If you’re planning to make a breaking change, first consider whether there are any non-breaking alternatives. It requires more thinking than just stamping on a new version number and calling it there, but the benefit is that consumers will continue to use your API without issue.
For example, if you were considering replacing a resource with another, consider instead adding that new resource and keeping the old one. Then, provide a notice to consumers about this new, improved resource.
The code below demonstrates how a resource can be added without affecting existing integrations:
"address": "25 First St., Cambridge, MA", // old
"street-address": "25 First St.", // new
"city": "Cambridge", // new
"state": "MA" // new
Here, the original resource address has been broken up into three new resources: street-address, city, and state. This allows consumers to adopt the new resources or stick with the old address resource.
How to Do API versioning
Realistically, your API will have to release a new version every so often. Things will come up that need to be changed and can’t be addressed without a breaking change, such as major bugs, security vulnerabilities, or performance improvements. Or, maybe the API was poorly designed from the outset and needs an overhaul.
When creating a versioning strategy, one of the most important things you can do is allow backward compatibility. Keep older versions of your API active and supported so that consumers may use them until deciding to upgrade. What you’re essentially doing is forking off the previous version of your API to create a new version while keeping the old version functional.
It’s your decision when to finally sunset old versions of your API. From usage data, you may see that v2 and v3 of your API are significantly higher in users than v1, and decide to deprecate v1 if the costs of potential lost users outweigh the costs of maintaining that version.
All changes to your API, from small updates to new releases, should be made clear to clients. If you need to sunset a feature or version of your API, always communicate this and give adequate warning to clients. Also, expect to upset some people and lose users — hopefully, not too many.
Here’s what a communication about a deprecated API component might look like:
Types of API Versioning
When it comes to actually labeling your new versions, there are several approaches, some of which might work better for your user base than others. Here are the most common ways to route client API calls to different API versions.
The most common way to version an API is in the URI path. This method employs URI routing to direct requests to a specific version of the API. The URI tells us not just what resource is targeted, but which version contains it.
The version can be indicated with a number (shown above), or with a date, name, or other identifier, as long as each version is unique. This video from Mulesoft further explains how to number your major updates, minor updates, and patches:
URI path versioning is relatively easy to understand and implement, but if you don’t keep previous versions active, replacing your old URIs with new version numbers will break any integrations that use the old version, and clients will need to update their software to work with your API.
This method also means you can’t update just one part of the API. Every endpoint needs to be updated, which is less flexible, more resource-intensive, and involves creating an entirely new API in each version. It also violates a key principle of API design that each resource should have its own unique URI.
In this method, the version number is included in the URI, but as a query parameter instead of in the path.
This approach is also relatively simple to implement and doesn’t require you to overhaul all your URIs at once when updating versions. It’s also easy for the client to switch to the new version in their request. If a client doesn’t specify the version number in their query, you can default to the newest version.
Custom Request Header
You can also set the version number using custom headers in requests and responses. This leaves the URI of your resources unchanged.
Finally, you can version your API with the Accept request HTTP header. The Accept header specifies which content types the client can process.
Versioning this way lets developers version individual resources, rather than the entire API at once, allowing for more control over versions. It also leaves a smaller footprint in the codebase since you’re not copying the entire API for your new version.
The downside is that APIs set up this way are more complex to implement and test than the more popular approaches above. You’ll have to track which parts of your API are in which version and figure out the logistics of serving the right version to each client.
Keep your integrations intact with API versioning.
Updating an API is necessary, but also risky. Without proper versioning, things break. And when things break, consumers lose trust and look for a more stable alternative.
With each change, aim to take as much burden off the customer as you can — that’s the ultimate goal of proper API versioning. Your users will thank you for it. Not literally, but they will continue to send requests your way.