"Your API will change. Either you version it on purpose, or you break clients by accident. Pick a strategy on day one, even if you don't ship v2 for years."
The Problem Versioning Solves
APIs accumulate decisions: field names, error formats, status code choices, default values. Some of those decisions turn out wrong. Some markets change underneath. You want to fix or extend the API without breaking the 10,000 clients already in production. Versioning is the contract you publish saying "this version is stable; the next version may differ."
The trick: choose where the version lives in the request — URL path, header, media type, or query parameter — and stay consistent.
The Four Strategies (and When Each Fits)
1. URL path versioning. https://api.example.com/v1/users vs /v2/users. Stripe, AWS, GitHub (currently), Twilio, most APIs you'd recognize.
- Pro: visible in logs and curl; cache-friendly; easy to route in any framework.
- Con: couples the URI to the version (purist REST argues each resource should have one canonical URI).
- Verdict: default choice for most APIs. Easy to teach, easy to operate.
2. Custom header versioning. X-API-Version: 2. LinkedIn (historically), some enterprise APIs.
- Pro: same URI across versions; clean for the REST purist.
- Con: invisible in logs unless you log headers; CDN caching needs
Vary: X-API-Version; less discoverable. - Verdict: works, but the operational tax is real.
3. Media-type versioning. Accept: application/vnd.example.v2+json. GitHub used this before v4; some hypermedia APIs.
- Pro: the version is part of the representation, which is the purest REST interpretation.
- Con: tooling (browsers, OpenAPI editors, curl users) handles this awkwardly; requires Vary; clients need to know the magic media type string.
- Verdict: theoretically pure, practically uncommon.
4. Query parameter versioning. /users?version=2. Some quick-and-dirty APIs.
- Pro: works without changing your framework's routing.
- Con: breaks the URL identity (two different version queries are two different resources); harder to cache; smells lazy.
- Verdict: avoid. URL path versioning gives you everything this does, more cleanly.
Date-Based Versioning (the Stripe Refinement)
Stripe uses path-style but with dates: /v1/charges for the path, plus a per-request header Stripe-Version: 2024-09-30.acacia that picks a snapshot of the API behavior. Clients lock in to the version they integrated against and only upgrade when they choose to. Each named version's behavior never changes.
This solves a real problem: "versions" come in many shapes (new fields, removed fields, changed defaults, renamed endpoints), and a single integer version ("v2") forces you to bundle changes. Date-based versions can be released continuously without breaking anyone.
Additive vs Breaking — The Rule That Buys You Time
You can skip versioning entirely if every change is additive:
- Adding a new field to a response → existing clients ignore it. Safe.
- Adding a new optional query parameter → existing clients don't send it. Safe.
- Adding a new endpoint → existing clients never call it. Safe.
- Adding a new status code or error case → existing clients with good family-dispatch handle it. Safe.
Versioning is for the breaking changes:
- Removing or renaming a field. Breaks any client that reads it.
- Changing a field's type or format. Breaks any client that parses it.
- Tightening validation (a previously-accepted payload now returns 422). Breaks clients that relied on the looseness.
- Changing the default value of an optional parameter. Subtle, but real.
Most production APIs add features for years before they need a v2. Default to additive; reach for versioning only when the new behavior genuinely can't co-exist with the old.
Deprecation — The Polite Goodbye
When you do need to retire an old version, signal it through the wire. Two relevant headers:
Deprecation: Sun, 01 Jan 2026 00:00:00 GMT— "this endpoint or version is officially deprecated as of this date." Clients can log a warning.Sunset: Wed, 01 Jul 2026 00:00:00 GMT(RFC 8594) — "this endpoint will stop responding after this date." Clients have a deadline.
Pair these with a clear changelog and migration guide. The headers are the wire signal; the docs are the human signal. Both are needed.
cwkPippa's Versioning Reality
/v1/ shows up. Until then, the cost of premature versioning would outweigh the protection.