API versioning: Without breaking clients
In short: Ways of developing an interface further without suddenly breaking the apps and programs that use it.
In more detail: As soon as third-party programs use an API, every change can potentially break their function. One distinguishes backward-compatible changes (new optional fields, new endpoints) from breaking ones (field removed or renamed, different type, changed meaning). Versioning makes breaking changes possible without forcing all users to switch immediately.
In Depth
Kinds of versioning
- In the path:
/v1/customers,/v2/customers. Simple and visible, hence very common. - In the header:
Accept: application/vnd.company.v2+jsonor a custom header. Clean URLs, but harder to test. - As a parameter:
?version=2. Rarely recommended. - Date-based: the client fixes a cut-off date (Stripe does this, for example) and gets the behaviour of that time.
Getting by without a new version
Many changes need no new version: add new fields, never remove or reinterpret existing ones, introduce new values carefully. Clients should ignore unknown fields (tolerant reader). Enumerated values are critical if clients crash on an unknown value.
Phasing out
An old version is not switched off overnight. Usual steps: announcement with a deadline, notes in the responses (Deprecation and Sunset headers), usage measurement per version and targeted information of the last users. Maintain as few versions as possible at the same time.
Tests
Consumer-driven contract tests (for example with Pact) automatically check whether a change violates the clients’ expectations. An OpenAPI description can be compared between versions to detect breaking changes.
See also: REST API design, APIs, Semantic versioning