The company changes checkout. The newest app understands additional order states; a mobile client installed a year ago does not. A partner has been asked to upgrade but has its own release schedule. Disabling the old contract today would break something customers already rely on.
API versioning allows the old and new ways of communicating to coexist. That independence in time is valuable. It also has a bill: testing, fixes, documentation, security maintenance and sometimes separate business behaviour.
Not every new field needs a new version
Before declaring v2, check whether the change is actually incompatible. An additional optional response field may be harmless to consumers that ignore unknown fields. But not all clients behave that way: some validate responses strictly and reject anything unexpected.
Renaming an existing field, changing what an order status means, introducing a required parameter or altering error semantics is much riskier. The question is not whether the schema still looks neat. It is how real consumers interpret the contract.
Sometimes the safer option is to introduce new behaviour alongside old behaviour. Sometimes a distinct version is justified. The version number should follow the compatibility problem rather than become a regular release decoration.
What does supporting two versions mean?
A public contract includes far more than a v1 segment in a URL. It includes data shapes, failure behaviour, limits, documentation, tests and security obligations. With several active versions, important changes may need to be validated in each.
The entire application does not have to be duplicated. Version-specific adapters can translate requests into one shared business model when the differences are only at the API boundary. But a changed interpretation of refunds or authorisation touches the domain itself. Calling that “just another controller” will not remove the complexity.
Versioning avoids a single forced migration day. Without an explicit end to the transition, however, a temporary bridge can become permanent legacy.
Be careful about promised shutdown dates
A useful policy answers: who is affected, what must change, how long will the old version be supported and how will everyone know migration is complete? For external partners, that is part of the commercial relationship, not only an engineering announcement.
I would first establish visibility into actual version usage. It is difficult to retire an API when nobody knows which clients still call it. Metrics by version, consumer identity and operation can help, provided logging does not expose secrets or unnecessary personal data.
Security fixes need a separate policy. If a serious problem appears in an old version, the company may not be able to wait until its planned end of life. It may need a compatible fix or an accelerated migration.
Before approving v2
Show the specific breaking change and the consumers it affects. Then compare a compatible extension, a temporary adapter and a new version with an agreed lifetime.
Contract tests can detect compatibility problems before release, though they cannot migrate a partner's application for it. The Azure Architecture Center API design guidance also covers backward-compatible changes and version coexistence.
An API version is not progress in itself. It is an agreement about how long consumers can stay in the past while the product moves forward. Both parties should understand the cost of that agreement.