Skip to content

Versioning

The version is in the path: every endpoint lives under /external/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 code you 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.
  • 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 operationId is renamed, so generated clients stay valid.
  • No existing error code is renamed or remapped to a different HTTP status.
  • No operation is narrowed to fewer kinds of key. An endpoint open to partner and provider keys stays open to both; a provider-only endpoint may be opened to partner keys later, but nothing published is ever closed. See which endpoints each key reaches.

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 sixteen error codes and the statuses they map to; the key sets of all three totals objects — the income statement’s ten, net_other_income_cents included, the balance sheet’s three and the cash flow report’s five; 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.

Anything not covered above lands as /external/v2. If that happens:

  • v1 is 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 v1 field to avoid cutting a v2.
  • Pin nothing but the major version. There is no minor version to track; /external/v1 is 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_basis and the effective period alongside any figure you keep. Both are returned on every report for exactly this reason: a number without them is not reproducible later. The effective period is the start_date / end_date pair on a range report, and the as_of_date on a balance sheet.
  • 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.