What we promise to preserve or extend, and how new enums are announced in advance.
Versioning and Compatibility
The version is in the path: all endpoints are under /v1.
There is no version header, and callers cannot select a version. At a given time, the same URL exposes the same contract to every merchant. info.version in the specification files (openapi/*.yaml) is a documentation version, not a way to pin behavior.
What Counts as a Breaking Change
There is one test: would a correct integration built from the previous documentation break because of this change?
Yes means breaking. No means nonbreaking, and we may release it at any time.
| Change | Breaking? | What you need to know |
|---|---|---|
| Add a response field | No | Your parser must ignore unknown fields. Strict JSON deserialization, such as Go's DisallowUnknownFields or some Java configurations, will fail here |
| Add an optional request field | No | Omitting it preserves previous behavior |
| Add an enum value (order state, event type…) | No | See below; this especially requires defensive handling |
| Add an error code | No | See below |
Reword the English message | No | message is human-readable and may change anytime. Branch on code, not message |
| Add an endpoint | No | |
| Remove a field, change its type, or change its meaning | Yes | |
Rename a code | Yes | |
| Add a required request field or tighten validation | Yes | Tighter validation has the same effect as a new required field: yesterday's valid request fails today |
| Remove an enum value / endpoint | Yes | |
| Narrow a field's allowed range, such as reducing amount precision | Yes |
⚠ One change may look like a bug fix but require your action: changing the same failure from 5xx to 4xx, or the reverse. This happened on 2026-08-12, when valid business rejections previously returned as 500 api_error became 4xx responses with an explicit code. Integrations with a workaround to retry 500 responses must remove it, or their retry logic may repeatedly submit requests that can never succeed. These changes are marked “Action required” in the Changelog.
Our Commitment on Enum Values
New state values are announced in the Changelog in advance.
This commitment also places a requirement on your integration:
Your
defaultbranch must treat the value as unknown and alert, rather than pretending to recognize it.
Three places require fallback branches:
| Location | Handling an unknown value |
|---|---|
Order/application status | Retain as unresolved; do not classify as success or failure, and alert |
| Webhook event type | Return 2xx (otherwise we keep retrying), store it unchanged, and alert |
Error response code | Classify and handle by type and HTTP status (see the three retry rules on the Errors page), and alert |
⚠ The wrong pattern is putting “processing” or “failed” in default:. It produces no error or alert, silently misrepresents a new state, and stays hidden until a user complains. We made this mistake server-side ourselves. Our current rule is to suspend and alert on every unknown upstream state, never default to processing.
Likewise, do not reject responses with exhaustive enum validation. An unfamiliar state must not crash your consumer process— that turns a purely additive change into an outage on your side.
How Breaking Changes Are Announced
We maintain two authoritative pages:
- Changelog—each entry states whether your action is required. Entries marked required will cause problems eventually if ignored; entries marked not required are purely additive. This log has been maintained since 2026-08-12; earlier changes were not individually recorded;
- Known Issues—unfixed defects and workarounds. Fixed entries are marked resolved and retained for a while, not immediately deleted; deletion would leave integrators who implemented workarounds unaware that they can remove them.
⚠ This page promises no notice period, parallel-version lifetime, or SLA. For contractual commitments—how many days' notice, how your technical contact is notified, or how long /v1 will be maintained—confirm with your account manager. Do not base capacity or scheduling assumptions solely on this document.
Three Minimum Requirements for Your Integration
Without these, even additive changes can break your system:
- Ignore unknown fields. Avoid deserialization settings that fail on one extra field;
- Every switch needs a default that alerts. See above;
- Branch on
code, notmessageor HTTP status alone. A 400 may mean either an invalid request or an unfulfillable transaction, and they require opposite retry handling.