API Versioning Strategies

intermediate
11 min

API Versioning Strategies

The day your API gets its first external consumer, you lose the freedom to change it casually. Renaming a field that a mobile app depends on breaks that app for every user until they update. Versioning is how APIs evolve without betraying existing clients. In this lesson we define what actually breaks clients, compare the three main versioning strategies, and lay out a humane deprecation process.

What Counts as a Breaking Change

Additive changes are safe: new endpoints, new optional request fields, new fields in responses (clients must ignore unknown fields, a rule worth documenting). Breaking changes include removing or renaming a field or endpoint, changing a field's type or format, tightening validation on existing inputs, changing error codes or status codes clients rely on, and changing authentication requirements. The whole point of versioning is to ship the second list without disturbing anyone still on the old contract.

Strategy 1: URL Versioning

The version lives in the path: /api/v1/products versus /api/v2/products.

text
GET https://api.shopcraft.com/v1/products/42 -> {"name": "...", "price": 79.99} GET https://api.shopcraft.com/v2/products/42 -> {"name": "...", "price": {"amountCents": 7999, "currency": "USD"}}

This is the most common approach (GitHub, Twitter historically, countless internal APIs) because it is unmissable: the version is visible in every log line, every browser test, every copied curl command. Routing v1 and v2 to different code paths or even different services is trivial. Purists object that /v1/products/42 and /v2/products/42 are the same resource with two URLs, but the operational clarity usually wins.

Strategy 2: Header Versioning

The URL stays clean and the version travels in a header, either custom (X-API-Version: 2) or via content negotiation with a vendor media type: Accept: application/vnd.shopcraft.v2+json. GitHub's modern API uses X-GitHub-Api-Version: 2022-11-28. This is the more RESTful design and keeps URLs permanent, at the cost of discoverability: versions are invisible in logs and URLs, harder to test in a browser, and easier to forget entirely, which means you must define what happens when the header is absent (usually: default to the oldest supported version, never the newest).

Strategy 3: Date-Based Pinning

Stripe's famous approach: each account is pinned to the API version (a date like 2026-03-15) that was current when it first integrated, and stays there until it explicitly upgrades or overrides per-request with a Stripe-Version header. The provider maintains transformation layers between adjacent versions. This is the gold standard for developer experience and the most engineering-intensive to operate; it suits platforms whose entire business is their API.

Choosing and Operating a Strategy

For most teams the pragmatic answer is URL versioning with coarse major versions only: v1, v2, never v1.3 in the URL (minor, additive changes need no version at all). Create v2 only when forced by accumulated breaking changes; every live version multiplies your testing and support surface, and the goal is to run as few as possible, ideally one or two.

Deprecating the Old Version

Retiring v1 is a process, not an announcement. Communicate a timeline (6 to 12 months for public APIs), emit warnings in responses via the Deprecation and Sunset headers so tooling can detect them, monitor traffic to identify remaining v1 callers and contact the noisy ones directly, then brown-out (serve temporary errors for short windows) before the final shutdown with 410 Gone. Every step exists because someone, somewhere, has not read your changelog.

Key Takeaways

  • Additive changes need no version; breaking changes require one.
  • URL versioning is the visible, operationally simple default; header and date pinning suit API-first platforms.
  • Version majors coarsely and keep as few versions alive as possible.
  • Deprecate with headers, timelines, traffic monitoring, and brown-outs, never a silent switch-off.

Next up: Error Handling and Validation, making failure a well-designed part of your contract.

API Versioning Strategies - REST APIs | CodeYourCraft | CodeYourCraft