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:
- 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.
- No field changes its JSON type.
- No field changes its meaning. Definitions are part of the contract: what
current_chargesincludes, which charges havecontributes_to_total, and that a child statement is one metered service point. - No enum value is removed or repurposed.
- A statement keeps its
statement_idwhen its bill is re-extracted or sent again. - 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:
serviceandkindasother,confidence.tierasreview, an unknown entry insignals_failedas a failed signal, and an unknownreason.codeby itscustomer_action_requiredflag. - Return
2xxfor an event type you do not recognize, and ignore it. - Treat an absent field and
nullalike. - Do not depend on key order, or on the order of
charges,sections,metersorchildren.delivered. - De-duplicate on the delivery id, and key what you store on
statement_id.
Every change is listed, newest first, in the changelog.