info.version of the OpenAPI document, and it is the one signal that the contract moved.
The three rules
1
Additive changes bump the minor version, with no notice
A new optional field, a new endpoint, a new event type, a new error code, a new enum value on a field you send us: all of these ship in a minor bump with no advance notice. Your integration keeps working through them, which is why they need none.
2
Breaking changes ship on a new path, never in place
We do not repurpose a field, tighten a type, or remove a route from
/v1. A change that cannot be made additively goes to /v2, and the two run side by side for at least 90 days so you can move at your own pace.3
Deprecations are announced on the wire, where you cannot miss them
A route on its way out keeps answering, and every one of its responses carries headers that name its replacement and its removal date. You do not have to be reading announcements to find out: your own logs tell you, well before anything stops working.
What counts as breaking
Deprecation headers
While a route is deprecated but still answering, every response it sends carries three headers:
They are set before anything else runs, so a 401 carries them just as a 200 does. That is deliberate: a caller whose credentials are stale is exactly the caller most likely to be running old code.
The first route to carry them is
POST /v1/book, superseded by POST /v1/checkout:
/v1/book, switch to /v1/checkout. It is the same operation under the name the rest of the platform uses, and it is where new behaviour lands.
The error-code enum is closed
error.code is a fixed set, published as an enum in the spec. The platform sends no code outside it, and every code in it has a producer. The spec and the errors page are kept in step with the platform’s own table, so the list you read is the list you can receive.
Adding a code is additive and lands in a minor bump, so keep a default branch for a code you do not recognise. Removing one is breaking.
What we deliberately do not do
- No dated versions in a request header. There is no
Jinko-Versionheader to pin. The contract version is a property of the document you read, not of the call you make. - No silent behaviour changes inside a version. If the answer to the same request changes in a way you can observe, the minor version moves, so
info.versionis enough to tell you something did. - No removals without the sunset window. A route that carries no
Sunsetheader is not going anywhere.
Where to look
- The served contract:
info.versionin the OpenAPI document. It is the version of the environment you fetched it from. - What changed: the contract version itself is the signal. Compare
info.versionagainst the one you last integrated against, and read a deprecated route’sDeprecationandSunsetheaders straight off your own responses. A public changelog is not published yet. - What a code means: Errors & troubleshooting carries the full enum with a remedy for each entry.
