Skip to main content
v2_6_balances holds the balances POST /v1/customers.get and POST /v1/entities.get return, already computed. You don’t filter out old plans, pick the current cycle, or add rollovers yourself: every row is a balance the API would show, with the same numbers. This page explains the three ideas you need to read them correctly.

1. One row per view

A customer and each of its entities can see a different balance for the same feature. The customer sees grants made at customer level. An entity sees those same customer-level grants, plus grants on its own plans. So v2.6 stores one balance per view:
  • the customer view: scope = 'customer', internal_entity_id null. This is POST /v1/customers.get.
  • one entity view per entity: scope = 'entity', internal_entity_id set. This is POST /v1/entities.get.
balance_id names the view: internal_customer_id:internal_feature_id:internal_entity_id, with the last part empty for the customer view. v2_6_breakdowns, v2_6_rollovers and v2_6_flags carry the same scope, so each view has its own rows.
Never add up balances across views. A customer-level grant appears in the customer view and again in every entity’s view, so a sum over all rows counts it many times. For a customer’s total, filter scope = 'customer'. For one entity, filter its internal_entity_id.

2. The API’s filter is already applied

The tables contain only what the API would return at as_of:
  • grants on plans whose status counts: active, plus past_due if your organization keeps past-due plans live. Ended, scheduled and expired plans add nothing.
  • grants that have not expired, and loose grants (not tied to any plan) that are still live.
  • rollovers that have not expired.
A customer who upgraded from Pro v1 to Pro v2 has one breakdown row from Pro v2, not one per plan they ever held. If you need the history, use v2_6_subscriptions, which keeps every status.

3. Rollovers first, then breakdowns in order

When usage is tracked, Autumn takes it from rollovers first (the one that expires soonest first), then from the breakdown rows in position order: position 1, then 2, and so on. position is the order of the API’s breakdown[] array. A balance’s totals add up from its rows:
  • granted is the sum of included_grant + prepaid_grant over its breakdowns, plus each rollover’s granted.
  • remaining is the sum of its breakdowns’ remaining, plus each rollover’s balance.
  • usage is the sum of its breakdowns’ usage, plus each rollover’s granted − balance.

Worked example

Customer cus_123 has two entities, user_1 and user_2. Each has a Seat plan that grants 100 pooled credits and 20 exports a month. The two seats’ credits add up into one shared pool of 200 credits at customer level, and the customer also has a one-off grant of 30 credits. user_1 has 10 exports rolled over from last month. Credits. The customer view has two breakdown rows. Each entity’s view repeats the same two rows, because both grants are at customer level. Exports. Only the entity views have rows, one for each entity’s own Seat plan, plus user_1’s rollover. The resulting balances: Three things to notice:
  1. There is no customer row for exports. Both exports grants are on entity plans, so the customer view has nothing for that feature, just as POST /v1/customers.get for cus_123 shows no exports balance.
  2. user_1’s exports balance includes the rollover: granted 20 + 10, remaining 5 + 4, usage 15 + 6.
  3. Summing every credits row would give 690 granted. The customer actually has 230.

Reading a customer’s balances

These queries return exactly what the API returns. They’re written in plain SQL; Querying has the ClickHouse and BigQuery versions.
Join entities through the customer, as above: an entity_id is unique within one customer only.

As of when

Expiry and reset dates are judged once per run, at the moment stored in v2_6_balances.as_of. A grant or rollover that expires after as_of is still in the tables until the next run. If you need a stricter answer, re-check expires_at yourself (null means it never expires):

Pools

With a pooled plan item, grants on several entities add up into one shared customer-level balance. In the tables that pool is one row in v2_6_breakdowns, with plan_id null and pooled_balance_id set. Its included_grant is the pool’s total. The plans that feed it are rows in v2_6_pooled_balance_contributions, joined on pooled_balance_id; they don’t appear as breakdown rows of their own.

Allocations

A customer can allocate shared credits to its entities (set in billing_controls.balance_allocations on v2_6_customers). The tables show the result the API shows:
  • Customer view: breakdown amounts are unchanged, and the balance gains allocated (credits reserved for entities) and unallocated (credits anyone can use).
  • Entity view: each shared row shows that entity’s share instead of the whole amount, with the allocation in allocation_amount. An entity with no allocation sees only the unallocated credits.
allocated and unallocated are null for features the customer doesn’t allocate.

Overage

v2_6_breakdowns.overage is the usage beyond what a grant gave:
Shared grants are read from the customer view (internal_entity_id null) so each is counted once. Grants an entity owns appear only in that entity’s view, so they come from rows with source = 'entity'. Overage only builds up on grants with price_billing_method = 'usage_based'; overage_allowed on the balance tells you whether the feature can go over at all.

Flags

On/off features, such as sso, are in v2_6_flags, not in v2_6_balances. Each view gets one row per feature it has. If several plans grant the same flag, the row is the one the API shows: an active plan’s before a past-due plan’s, then a loose grant, then anything else.