Versioning
The version is in the path: every endpoint lives under /external/v1.
What we may change within v1
Section titled “What we may change within v1”Additive changes ship within v1. New fields on an existing response, new endpoints, new error codes, new enum members. These land without a version bump and without prior coordination.
So parse leniently: ignore fields you do not recognise, and do not use a strict schema validator that rejects unknown properties. A client that fails on an unexpected key will break on a change that was safe for everyone else.
Specifically, plan for:
- New keys appearing in any object, including inside the full statement’s nested records.
- New error codes. Match on the
codeyou know and fall back to the HTTP status for anything else — the status is always meaningful even when the code is new to you. - New endpoints appearing in the reference.
What we will not change within v1
Section titled “What we will not change within v1”- No field is removed, and no field changes meaning. If a value’s definition needs to change, the new definition arrives as a new field.
- No field changes type, including the integer-cents representation of money.
- No path or
operationIdis renamed, so generated clients stay valid. - No existing error code is renamed or remapped to a different HTTP status.
That last set includes some specifics worth naming, because they are committed and can no
longer be withdrawn inside v1: the tax identifiers on the discovery records (tax_id on a
provider, ein on an entity); the ten error codes and the statuses they map to; the ten
keys of the totals object, net_other_income_cents included; and the presentation hints
carried by the full statement (title_tooltip, percentage_comment) — which you should
ignore, but which are published and will keep arriving.
Breaking changes
Section titled “Breaking changes”Anything not covered above lands as /external/v2. If that happens:
v1is maintained in parallel — a v2 does not switch off v1.- The migration window is agreed with you in advance, not announced as a deadline.
- We will not change the meaning of a
v1field to avoid cutting av2.
Practical advice
Section titled “Practical advice”- Pin nothing but the major version. There is no minor version to track;
/external/v1is the whole contract. - Log unknown fields rather than failing on them. It gives you a cheap signal that something was added, without an outage.
- Store the
accounting_basisand the effective range alongside any figure you keep. Both are returned on every report for exactly this reason: a number without them is not reproducible later. - Treat this reference as the contract, not any document we have sent you. It is generated from a specification that lives beside the code and is checked against the running routes on every change, so it cannot quietly drift out of date.