Data model
A subscription is three layers: the timeline records what was agreed, the engine computes what to bill, and the ledger records what was charged.
One chain, many versions
The id returned at creation is the chain id — fixed for the life of the
subscription. Each structural change (plan replacement, direction or cadence
change, scheduled cancellation) appends a new version to the chain rather
than mutating the current one, so the billing history stays immutable.
You never address a version directly. GET /v1/subscriptions/{id} takes the
chain id and returns whatever version runs today; its planId and status
reflect that version, even after several changes.
Timeline segments
Within a version, the timeline is a sequence of segments — immutable rows, each covering a date range and the products billed in it. A mid-cycle change doesn't edit a segment; it splits the timeline into a new segment, which is how proration is expressed (full new charge minus what was already billed), not as a delta calculation.
Each segment's products feed a billing schedule — one per (subscription, priceId) — which the engine reads to decide when the next charge lands (see
Billing & cadence).
versionId is for diagnostics only
Webhook payloads carry a versionId alongside the chain subscriptionId. It
identifies the internal version and is useful for support, but it is not a
reconciliation key — it changes on every structural change. Always reconcile on
subscriptionId (or partnerReferenceId), never versionId.