Concept · Networking & Delivery

API Versioning

01

Why this matters

You ship v1 of your API. Customers integrate. Six months later, you need to rename a field, change a response shape, drop a deprecated endpoint. Every existing customer integration will break. They didn't sign up for a maintenance project on your schedule.

API versioning is the discipline of evolving your API without breaking existing consumers. Get the strategy right and you can ship breaking changes for years; get it wrong and you create permanent technical debt with thousands of integrations frozen on v1.

02

Where the version lives

StrategyExampleProsCons
URL path/v1/users vs /v2/usersVisible, cacheable, easy to test in browserCouples version to URL — REST purists hate it
Subdomainv2.api.example.comDifferent infra per version, easy traffic splitCORS pain, infra duplication
HeaderAccept: application/vnd.api+json;version=2"Cleanest" RESTInvisible, hard to debug, breaks browser testing
Query param?api_version=2Easy to testConfused with business params
Date-basedHeader Stripe-Version: 2023-10-16Tiny granular versions; per-account pinningServer must maintain N versions; complex internally
03

The Stripe model — date-based versioning

Stripe's approach is the gold standard for high-stakes APIs:

  • Every breaking change creates a new version dated to that release (e.g. 2023-10-16).
  • Each customer is pinned to whatever version their account was created at.
  • API requests can override via Stripe-Version header.
  • Stripe maintains all versions simultaneously — they have versions from 2011 still working.
  • Old versions implemented as transformation layers on top of the current internal model. New version is the default; older versions translate request/response on the wire.

Result: Stripe can ship breaking changes weekly. Old integrations work forever. Customers upgrade explicitly when they want new features. Cost: significant engineering complexity to keep N versions running.

04

Pragmatic guidelines

  • Prefer additive changes. Add fields, never remove. Add endpoints, don't repurpose existing. Old clients ignore new fields → no breakage. Most "breaking changes" can be reformulated as additive.
  • Reserve major versions for true breakage. Going from v1 → v2 should be rare (years apart). Most evolution stays within a major version.
  • Deprecate before removing. Add Deprecation + Sunset headers. Email customers. Provide a migration path. Give 6-12 months minimum.
  • Document on day one. OpenAPI / Swagger / API explorer. Consumers can't migrate without docs.
  • Test old versions in CI. If v1 still ships, tests for v1 still run. Otherwise it'll silently break.
The temptation to avoid

"We'll just version when needed." Translates to "we'll never version, we'll just break things and email people." Decide on the strategy day one. Cheaper to have unused versioning than to retrofit it.

05

Deep dive — handling deletes the additive way

You want to remove the nickname field from /users. Removing it would break old clients. Additive solution:

  1. Stop populating nickname in new records. Field still exists in schema, returns null for new users.
  2. Document the field as deprecated.
  3. For 12 months, monitor: who is still calling expecting non-null? Email those clients.
  4. After deprecation period: stop returning the field. Old clients see "missing key" — most JSON parsers handle gracefully. Hard breakers get a 12-month notice.

Same for renames: add display_name; populate both fields; deprecate nickname; eventually drop it. Two writes for the deprecation period; old clients keep working; new clients use the new name.

If a real breaking change is unavoidable: bump major version. Run both. Set a sunset date for the old major. Communicate. Repeat.

06

Real-world

Stripe

Date-based, per-account pinning

Every breaking change = new version dated. Versions kept indefinitely. Internal transformation layers handle old contracts.

GitHub REST API

URL versioning + media types

/v3/ path + Accept: application/vnd.github.v3+json for sub-version features. Now mostly pushing toward GraphQL.

Twilio

URL versioning

/2010-04-01/ in path. Each major version a new path. Maintained for years past launch.

AWS APIs

Date-based per service

Each AWS service uses an internal API version date. Backwards compatibility is maintained essentially forever — APIs from 2006 still work.

07

Used in problems

URL shortener APIs version via path (/v1/shorten) for clean separation. E-commerce APIs use URL + sub-versioning for minor field additions. Payment gateway uses Stripe-style date-based versioning for max compatibility. News feed mobile API versions independently from web.

Next up