The promise
/v1 is stable. A response only ever gains fields, enum values or endpoints; nothing is renamed, removed or re-typed inside /v1. Anything that would break a correctly written client ships under /v2, and /v1 keeps working alongside it.
"Correctly written" means: ignore fields you do not know, accept new enum values gracefully (treat an unknown status as "not one I handle"), and branch on status and the type slug of an error, never on detail.
What may change without notice
- New optional fields in responses and webhook payloads.
- New webhook event types (you only receive the ones you subscribed to).
- New endpoints and new optional request fields.
- The wording of
detailandtitlein errors. - Rate-limit numbers going up.
- Default page sizes staying within the documented bounds.
What we treat as breaking
- Removing or renaming a field, endpoint or event type.
- Changing a field's type or units.
- Making an optional request field required.
- Tightening validation on input we used to accept.
- Changing an HTTP status for a documented situation. (We did this once, on 2026-09-21: the voucher endpoint's
402became422 balance-insufficient. No integration was affected and it is recorded in the changelog. It will not happen again inside/v1.)
Deprecation
Nothing in /v1 is deprecated today. When something is:
- It is announced in the changelog with a sunset date at least 6 months out.
- Responses on the affected path carry
Deprecation: trueandSunset: <date>headers. - Owners of keys that still use it get an email at 90, 30 and 7 days.
- After the sunset date it returns
410 Gonewith atypepointing at the migration note.
Keeping up
The changelog is the record. The OpenAPI document at /openapi/cvos.v1.yaml carries info.version; diff it against the copy you built with.