---
title: "API Versioning"
description: "Strategies and best practices for versioning your APIs to manage change without breaking consumers"
url: "https://seriousmonkeybusiness.shermett.me/guides/publish-apis/versioning"
image: "https://seriousmonkeybusiness.shermett.me/_og/d/c_Ocean.takumi,title_API+Versioning,description_Strategies+and+best+practices+for+versioning+your+APIs+to+manage+change+without+breaking+consumers,props_eyJ0aGVtZSI6eyJtb2RlIjoibGlnaHQiLCJjb2xvcnMiOnsicHJpbWFyeSI6IiMwMDk5MzMifX19,p_Ii9ndWlkZXMvcHVibGlzaC1hcGlzL3ZlcnNpb25pbmci,s_fODwFCrp2lRhd6J4.png"
---

# API Versioning

APIs evolve. Features get added, schemas change, and sometimes breaking changes are unavoidable. A solid versioning strategy lets you move forward without leaving your consumers behind.

## [Why Version Your APIs?](#why-version-your-apis)

Every API is a contract between you and your consumers. When you change that contract — renaming a field, removing an endpoint, or altering response structures — existing integrations can break. Versioning gives you a controlled mechanism to introduce changes while maintaining backward compatibility.

The cost of breaking changes

A single unannounced breaking change can break hundreds of integrations overnight. Always version your API before introducing incompatible changes, and give consumers a clear migration timeline.

### [What Counts as a Breaking Change?](#what-counts-as-a-breaking-change)

Not all changes require a new version. Understanding the difference is key.

Requires a New Version

-   Removing or renaming an endpoint
-   Removing or renaming a response field
-   Changing an existing field's type
-   Adding a new **required** parameter
-   Changing authentication requirements
-   Altering error response formats

Safe to Ship Anytime

-   Adding a new **optional** parameter
-   Adding a new field to a response
-   Adding a new endpoint
-   Supporting a new content type
-   Improving error messages (same codes)

## [Versioning Strategies](#versioning-strategies)

There are several approaches. Each comes with trade-offs around complexity, discoverability, and developer experience.

URL Path

Header

Query Param

The most common and most visible approach. The version number is embedded directly in the URL path.

```bash
# Version 1
GET https://api.seriousmonkey.biz/v1/bananas

# Version 2
GET https://api.seriousmonkey.biz/v2/bananas
```

**Pros:** Extremely explicit, easy to understand, simple to route, works with any HTTP client.

**Cons:** Increases the number of URLs, can lead to large codebases if not managed carefully.

This is the approach used by Stripe, GitHub, Twilio, and most major public APIs. **We recommend it for most teams.**

The version is specified in a custom request header, keeping URLs clean.

```bash
GET https://api.seriousmonkey.biz/bananas
Accept-Version: v2
```

**Pros:** Clean URLs, version can be changed without updating links.

**Cons:** Less discoverable, harder to test in a browser, requires documentation.

The version is passed as a query parameter on each request.

```bash
GET https://api.seriousmonkey.biz/bananas?version=2
```

**Pros:** Easy to implement and test, doesn't clutter the path.

**Cons:** Easy to forget the parameter, can conflict with other query parameters.

### [Strategy Comparison](#strategy-comparison)

| Strategy    | Visibility | URL Cleanliness | Caching         | Ease of Use |
| :---------- | :--------- | :-------------- | :-------------- | :---------- |
| URL Path    | High       | Low             | Excellent       | Excellent   |
| Header      | Low        | High            | Requires config | Moderate    |
| Query Param | Medium     | Medium          | Requires config | Good        |

## [Managing the Version Lifecycle](#managing-the-version-lifecycle)

A good versioning strategy goes beyond choosing a format. You need a clear lifecycle for how versions are introduced, maintained, and eventually retired.

### [Version Lifecycle Phases](#version-lifecycle-phases)

**Active** — The current recommended version. All new features and bug fixes land here first.

**Maintained** — Still supported. Receives critical bug fixes and security patches, but no new features.

**Deprecated** — Scheduled for removal. Consumers receive warnings in response headers and should migrate.

**Retired** — No longer available. Requests return `410 Gone` with migration guidance.

### [Communicate Deprecation Clearly](#communicate-deprecation-clearly)

When deprecating a version, give consumers plenty of notice and make migration easy.

```bash
# Include deprecation headers in responses
Deprecation: true
Sunset: Sat, 01 Nov 2026 00:00:00 GMT
Link: <https://docs.seriousmonkey.biz/migration/v1-to-v2>; rel="successor-version"
```

**Pro Tip:** Give at least 6 months notice before retiring a major version. Provide migration guides, tooling, and personal outreach to high-value consumers.

## [Best Practices](#best-practices)

Start with v1

Don't prematurely version. Ship v1 and only create v2 when you actually have breaking changes. Over-versioning creates maintenance burden without adding value.

Use semantic intent

Major versions for breaking changes, minor for additive features within a version. This gives consumers a clear signal about what to expect from each release.

Keep old versions running

Support at least the previous major version during migration periods. Your consumers have production systems that depend on the contract you published.

Automate compatibility checks

Use contract testing (tools like Pact or Schemathesis) to catch breaking changes before they reach production. Make these checks part of your CI pipeline.

Sunset responsibly

Never retire a version without advance notice, migration docs, and a grace period. Monitor usage metrics and reach out proactively to consumers still on old versions.

Related reading

For tips on making your API documentation clear and developer-friendly, check out our [Document Your APIs](https://seriousmonkeybusiness.shermett.me/guides/document-apis) guide.