API Versioning and Backward Compatibility: A Practical Engineering Guide
How to version APIs: breaking vs non-breaking changes, URL, header and date-based versions, Deprecation and Sunset headers, and compatibility testing.
How should you version an API?
Prefer additive, backward-compatible changes; introduce a new version only for unavoidable breaking changes; choose one versioning approach (URL path, header or date-based) and use it consistently; announce deprecations with dates, migration guides and the Deprecation and Sunset response headers; track usage of old versions; and test compatibility automatically. The goal is to change the API without breaking the people who depend on it.
This guide is for API owners and engineers. For documentation, see API documentation best practices; for partner ecosystems, SaaS integration marketplaces.
Key takeaways
- Know what counts as breaking.
- Make additive changes the default.
- Pick one versioning scheme and document it.
- Deprecate with dates, headers and direct contact.
- Keep old versions working until the sunset date.
- Run contract tests for every supported version.
Breaking vs non-breaking changes
| Usually non-breaking | Usually breaking |
|---|---|
| Adding an optional request field | Making a field required |
| Adding a response field | Removing or renaming a field |
| Adding an endpoint | Removing an endpoint |
| Adding an enum value (if clients tolerate it) | Changing a field's type or format |
| Relaxing validation | Tightening validation |
| New optional query parameter | Changing default sorting, paging or error codes |
Versioning approaches
| Approach | Example | Notes |
|---|---|---|
| URL path | /v1/orders, /v2/orders | Simple to route and understand |
| Header or media type | Accept: application/vnd.example.v2+json | Stable URLs; less visible |
| Date-based | A version header pinned to a date | Fine-grained; used by Stripe (Stripe docs) |
| No explicit versions | Additive changes only | Requires discipline; still need a plan for breaks |
Deprecation and sunset
Publish a deprecation policy with minimum support periods. When deprecating, announce it in the changelog and by email to known clients, add migration guides, and return the Deprecation header (RFC 9745) and, when a removal date is set, the Sunset header (RFC 8594) on affected responses (RFC 9745; RFC 8594). Monitor which clients still call old versions and contact them before removal. Google's API design guidance is another useful reference (Google Cloud).
Mobile apps and long-lived clients
Mobile apps on users' devices cannot all be updated at once. Keep APIs compatible with app versions still in use, track app versions in requests, use minimum supported version checks with friendly upgrade prompts, and plan backend changes around store release cycles. See mobile app API integration.
Testing compatibility
- Compare OpenAPI descriptions between releases and flag breaking changes in CI.
- Run consumer-driven contract tests for key clients.
- Keep regression tests for each supported version.
- Monitor error rates by client and version after releases.
Hypothetical example: a logistics API
This example is hypothetical. A logistics platform needed to split an address field into structured parts. It added the new fields alongside the old one, documented the change, and released v2 only for clients that wanted the old field removed. v1 responses carried a Deprecation header and, six months later, a Sunset header with a date. The team tracked v1 usage by client and contacted the remaining integrators before switching it off.
Common mistakes
- Breaking changes shipped without a new version.
- Several versioning schemes in one API.
- Removing versions without warning or usage data.
- Forgetting older mobile app versions.
- No automated check for breaking changes.
Related guides
- API integration reliability for retries and idempotency.
- API gateways for routing versions.
- Zero-downtime deployments for releasing changes safely.
- Integration architecture patterns for event schema versioning.
Conclusion
API versioning is mostly about avoiding breaks: change additively, version when you must, deprecate transparently with dates and headers, and test compatibility automatically. Clients trust APIs that change predictably.
Evolving an API others depend on?
ZSpace Labs is an India-based, remote-first technology studio working with Australian and international businesses on APIs and integrations and mobile apps that consume them. If it would help to plan a versioning strategy, we are happy to talk it through.
Common questions.
Anything that can make existing clients fail: removing or renaming fields or endpoints, changing types or formats, making optional inputs required, changing error codes or behaviour, tightening validation, or changing authentication. Adding optional fields or new endpoints is usually non-breaking, provided clients ignore unknown fields.