Docs: Compatibility and versioning

Compatibility and versioning

Every payload carries schema_version, a semantic version. Within a major version, we only ever add.

Change Version Examples
Breaking major A field removed or renamed, a type changed, a definition changed
Additive minor A new field, a new enum value, a new event type, a new failure code
Neither patch Clearer documentation; better extraction that keeps every field's meaning

Within a major version we promise:

  1. No field is removed or renamed. A field we plan to retire is announced as deprecated and keeps being sent until the next major version.
  2. No field changes its JSON type.
  3. No field changes its meaning. Definitions are part of the contract: what current_charges includes, which charges have contributes_to_total, and that a child statement is one metered service point.
  4. No enum value is removed or repurposed.
  5. A statement keeps its statement_id when its bill is re-extracted or sent again.
  6. A field that is always present stays always present.

A value that was wrong becoming right is not a change of meaning. It arrives as a new version of the statement. When an improvement moves values systematically, for example correcting a unit for one utility, the changelog says so.

A new major version runs beside the old one. You move when you choose, and the old version keeps being produced for at least six months after the new one is available to you. We retire an old version only after at least 90 days' written notice, and we never produce more than two major versions at once. Your agreement may give you a longer overlap, but never a shorter one.

What you need to do so that every minor version is safe to receive without code changes:

  • Ignore fields you do not recognize, at every level, including inside arrays.
  • Treat an unrecognized enum value as its catch-all: service and kind as other, confidence.tier as review, an unknown entry in signals_failed as a failed signal, and an unknown reason.code by its customer_action_required flag.
  • Return 2xx for an event type you do not recognize, and ignore it.
  • Treat an absent field and null alike.
  • Do not depend on key order, or on the order of charges, sections, meters or children.delivered.
  • De-duplicate on the delivery id, and key what you store on statement_id.

Every change is listed, newest first, in the changelog.