API versioning fails when it surprises people. A perfectly designed URL scheme cannot save a platform that changes behavior without warning, deprecates too aggressively, or leaves old versions alive with no support story.
The goal is not to avoid breaking changes forever. It is to make change survivable.
Context
Public API consumers need predictable change windows, stable contracts, and clear migration paths. The existing informal approach works while consumers are close to the team, but becomes brittle as integrations grow.
Decision
Use additive changes by default, reserve breaking changes for explicit version boundaries, and publish deprecation signals in documentation, response headers, and account communication.
Alternatives
- Keep a single evergreen API and avoid explicit versions.
- Version every endpoint independently.
- Use date-based global versions for all behavior.
Consequences
Consumers get a clearer contract, but the platform team must maintain version usage metrics and migration examples.
Define what versioning protects
Does a version protect response shape, validation rules, authentication behavior, pagination, error codes, or all of the above? Write it down. Consumers need to know whether a field can appear, disappear, or change meaning.
Ambiguity turns every deploy into a compatibility risk.
Make deprecation observable
Deprecation notices should show up in docs, dashboards, headers, and account communication. If a customer only learns about a breaking change when their integration fails, the process did not work.
Track usage by version and endpoint. That data tells you who needs help and whether a migration is realistic.
Prefer additive change
Add fields, add endpoints, and add opt-in behavior before replacing existing contracts. When removal is necessary, provide migration examples that match real client code.
Developers forgive change more easily when the path forward is concrete.



