Quick answer: API versioning is how you change endpoints, fields or behavior without instantly breaking every app that depends on you. Common approaches put a version in the URL (/v1/orders), in a header, or in the media type. Pick one strategy, document it, avoid breaking changes inside a version, and give consumers a clear deprecation window before you shut an old version down. Good versioning is part of API design, not an afterthought when something already broke in production.
Why versioning shows up
The moment more than one client uses your API (a mobile app, a partner integration, an internal admin tool), you lose the ability to change things freely. A renamed field or a stricter validation rule can take down someone else’s release.
If you are still framing the basics for stakeholders, start with what an API is and solid REST API design principles. Versioning sits on top of that foundation.
What counts as a breaking change
Treat these as breaking unless you have explicit compatibility rules that say otherwise:
- Removing a field or endpoint
- Renaming a field
- Changing a field’s type or meaning
- Making an optional field required
- Changing authentication requirements
- Altering error codes or response shapes clients parse
- Tightening rate limits without notice in ways that fail previously valid traffic
Usually non-breaking:
- Adding optional fields
- Adding new endpoints
- Adding optional query parameters
- New error codes that old clients ignore
- Performance improvements that preserve contracts
When in doubt, ask: “Could a carefully written client fail if we ship this?” If yes, bump a version or avoid the change.
Common versioning strategies
URL path versioning
Examples: /api/v1/customers, /api/v2/customers
Pros: Obvious, easy to route, easy to discuss in tickets.
Cons: Feels noisy; purists argue URIs should not encode versions. In practice it is the most widely understood approach for public HTTP APIs.
Query parameter versioning
Example: /api/customers?version=1
Pros: Simple to add.
Cons: Easy to omit by accident; caching and logging are messier; less visible than path versioning.
Header versioning
Example: Accept: application/vnd.myapp.v2+json or a custom API-Version: 2 header
Pros: Cleaner URLs; aligns with content negotiation.
Cons: Harder to try in a browser; developers forget headers; support and debugging need better docs.
No explicit version (evolution style)
Some teams only add fields and never remove anything, using feature flags and careful compatibility. That can work for internal APIs with coordinated deployments. It fails when external clients move slowly.
For most business APIs shared with partners or mobile apps, explicit versions (often in the path) are easier to operate.
Practical rules that prevent pain
- Version from the first public release. Retrofitting is harder.
- Do not create v2 for trivia. Additive changes stay in v1.
- Keep v1 running while v2 proves itself. Overlap periods matter.
- Document migration. Field mapping tables beat tribal knowledge.
- Instrument usage by version. You cannot retire what you cannot measure.
- Automate contract tests so new releases do not silently alter v1.
- Ship API error handling that stays stable inside a version so clients can retry safely.
OpenAPI/Swagger specs help here. Publish a spec per version and treat it as part of the product. See our notes on the OpenAPI Specification for documentation habits that age well.
Deprecation without drama
A calm deprecation policy looks like this:
- Announce early in developer notes and email to registered consumers
- Mark the old version as deprecated in docs and, if possible, in response headers
- Give a dated sunset (for example 6 to 12 months for external partners)
- Offer parallel run and a migration guide
- Monitor traffic; chase stragglers personally if a big partner lags
- Only then return 410/404 or shut the route down
Internal APIs can move faster, but still need a Slack announcement and a sprint of consumer updates. Custom API development projects should include this policy in the handover, not as a footnote.
Versioning and gateways
If you use an API gateway, you can route /v1 and /v2 to different services, apply different rate limits and retire routes centrally. Gateways do not replace good contracts; they make multiple versions operable.
Security rules (API security basics) should be version-aware too. Do not leave an old version running with weaker auth because “only one legacy client uses it” without a hard deadline.
Mobile and partner realities
Mobile apps do not update on your schedule. Users stay on old builds for months. Partners integrate once and vanish until something breaks. That is why overlapping versions exist.
Plan for:
- Minimum supported app versions tied to API versions
- Feature detection instead of brittle assumptions
- Server-side defaults when new fields are missing
- Chatty but clear changelog entries
Example version policy you can paste into a README
Current version: v1
Version location: URL path prefix /api/v1
Breaking changes: require /api/v2 and a migration guide
Additive changes: allowed in v1 without a bump
Deprecation notice: minimum 90 days for internal clients, 180 days for external partners
Sunset header: send Deprecation and Sunset style notices where practical
Support contact: engineering alias listed in the developer portal
Adjust the day counts to your market. Regulated partners may need longer. Consumer mobile apps almost always need longer than internal scripts.
Testing compatibility
Contract tests should run on every build for each supported version. Smoke-test older SDKs against staging. When you add a field, verify old clients ignore it. When you add an endpoint, verify authorization defaults are safe.
Consumer-driven contract testing (where clients publish expectations) helps larger organizations avoid silent breaks. Even a small team can keep a folder of representative request/response fixtures per version and replay them in CI.
FAQ
Should every endpoint share one global version?
Most teams version the API as a whole (/v1/...). Fine-grained per-resource versions rarely repay the complexity.
Is GraphQL versioned the same way?
GraphQL often evolves by adding fields and deprecating old ones in a single schema. You still need discipline; the mechanics differ from REST URL versions. See GraphQL vs REST when choosing style.
Can I skip versioning for a private app API?
Only if you deploy front end and back end together every time and accept coordinated releases. The moment a second client appears, revisit that choice.
How many versions should we keep alive?
As few as possible: typically current and previous. A third is a smell that deprecation is stalling.
Change the API on purpose, not by accident
API versioning is how you respect other people’s release cycles while still improving your product. Choose a clear strategy, reserve new versions for breaking changes, measure traffic and deprecate with dates. If you need help designing or integrating APIs that partners can rely on, see Custom development.