API Design Best Practices

API Versioning Best Practices: The Complete Guide

Your API will change. Users will add new features, deprecate old endpoints, and evolve data structures. Without a solid versioning strategy, you'll break existing clients every time you ship an update. This guide covers every major API versioning approach, when to use each one, and real-world examples from Stripe, GitHub, Twitter, and more.

Quick Takeaways

  • URI path versioning (/v1/users) is the most common and easiest to debug. Use it for public APIs.
  • Header versioning keeps URIs clean but requires tooling to inspect. Use it for internal or B2B APIs.
  • Content negotiation (Accept header) is the most RESTful but hardest to implement. Use it for mature platforms.
  • Never break v1 — always introduce v2, v3, etc. and deprecate old versions with clear timelines.
  • Document deprecation with sunset headers, migration guides, and advance notices (90+ days minimum).

Why API Versioning Matters

APIs are contracts. When you change the response format, rename fields, or remove endpoints, you break applications that depend on your API. Versioning allows you to evolve your API while maintaining backward compatibility for existing users.

Consider Stripe's approach: their /v1/charges endpoint has existed for years. When they introduced new features, they didn't change the existing response — they added fields. When they needed breaking changes, they introduced /v2/ and gave users months to migrate. This is why Stripe has one of the best developer reputations in the industry.

5 API Versioning Strategies Compared

1. URI Path Versioning

The most straightforward approach: include the version number directly in the URL path.

GET https://api.example.com/v1/users
GET https://api.example.com/v1/users/123
POST https://api.example.com/v2/users

Pros:

Cons:

When to use: Public APIs, developer-facing services, and any API that needs to be easy to debug.

Used by: Stripe, GitHub, Twitter, Shopify, Twilio

2. Query Parameter Versioning

Pass the version as a query string parameter.

GET https://api.example.com/users?version=1
GET https://api.example.com/users?v=2

Pros:

Cons:

When to use: Internal APIs, simple services, or when URI cleanliness is a priority.

3. Custom Header Versioning

Use a custom HTTP header to specify the API version.

GET https://api.example.com/users
X-API-Version: 1

GET https://api.example.com/users
Accept-Version: v2

Pros:

Cons:

When to use: B2B APIs, internal microservices, or when working with sophisticated API consumers.

Used by: Fastly, some GitHub Enterprise APIs

4. Content Negotiation (Accept Header)

Use the standard HTTP Accept header with a custom media type to specify version.

GET https://api.example.com/users
Accept: application/vnd.example.v1+json

GET https://api.example.com/users
Accept: application/vnd.example.v2+json

Pros:

Cons:

When to use: Mature platforms, REST purists, or when you need fine-grained control over response formats.

Used by: GitHub API (primary method), Heroku

5. Media Type Versioning

Similar to content negotiation but focuses on the response format version specifically.

POST https://api.example.com/users
Content-Type: application/vnd.example.user.v1+json

When to use: When request/response schemas evolve independently of API behavior.

Real-World Examples

GitHub API (v3 → v4)

GitHub uses Accept header versioning for their REST API:

Accept: application/vnd.github.v3+json

When they launched GraphQL, they created an entirely new endpoint (/graphql) rather than versioning it. This is a smart pattern: use REST for CRUD operations, GraphQL for complex queries.

Stripe API

Stripe uses URI path versioning and has maintained remarkable backward compatibility:

https://api.stripe.com/v1/charges
https://api.stripe.com/v1/customers

Stripe also supports date-based versioning — you can send a Stripe-Version: 2020-08-27 header to get the API behavior as it existed on that date. This is brilliant for long-running applications that need predictable behavior.

Twitter API v2

Twitter went through a major API overhaul. v1.1 used URI versioning, and v2 continued the pattern:

https://api.twitter.com/1.1/statuses/home_timeline.json
https://api.twitter.com/2/tweets

The v2 API also introduced more granular endpoints and better pagination, showing how versioning enables fundamental redesigns.

Deprecation Strategy: The Other Half of Versioning

Versioning is useless without a solid deprecation plan. Here's how to retire old versions without angering users:

1. Announce Early and Often

Give at least 90 days notice before deprecating a version. Better: 6-12 months for major changes. Communicate via:

2. Use Deprecation Headers

Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: <https://docs.example.com/migration/v1-to-v2>; rel="deprecation"

These standard HTTP headers tell clients exactly when the API will sunset and where to find migration docs.

3. Provide Migration Guides

Every version change should have a migration guide that covers:

4. Monitor Usage

Track which versions are still in use and by whom. Reach out to heavy users personally before sunsetting.

Versioning Anti-Patterns to Avoid

🚫 Breaking Changes Without Version Bump

Never remove fields, change types, or alter behavior in a "compatible" update. If it breaks existing clients, it needs a new version.

🚫 Too Many Versions

Don't support v1, v1.1, v1.2, v2, v2.1, v2.2, v3 simultaneously. Pick 2-3 versions max and deprecate aggressively.

🚫 Vague Deprecation Timelines

"Will be deprecated soon" is useless. Give exact dates: "Deprecated on Jan 1, 2026. Sunset on Jun 30, 2026."

🚫 Inconsistent Versioning Strategy

Don't mix URI versioning for some endpoints and header versioning for others. Pick one pattern and stick to it.

Our Recommendation

For most public APIs: Use URI path versioning. It's the easiest to understand, debug, and document. Start with /v1/ and plan for /v2/ from day one.

For internal/B2B APIs: Consider header versioning. Your consumers are more sophisticated, and you can work with them directly during transitions.

Whatever you choose: Document it clearly, deprecate slowly, and never break existing clients without warning.

Related Resources

Share this guide

Help others discover this guide by sharing it.

About this guide: Part of the DevKits API Design series. Last updated March 2026. This guide covers industry best practices based on analysis of Stripe, GitHub, Twitter, Shopify, and other developer-first APIs.