Skip to main content

The pricing-preview pipeline

Most billing surfaces answer one of two backward-looking questions: “what did we already charge” (the wallet ledger, the usage-records feed, invoices) or “what has been invoiced so far” (billing documents). The pricing-preview pipeline answers the forward-looking question finance ops actually asks at period close: what would this month look like if we closed it right now. Five scoped preview endpoints project the answer, each over one billing engine’s inputs:
  • POST /billing/aiaas-usage-pricing/preview — AI usage charges
  • POST /billing/marketplace-rev-share/preview — marketplace builder payouts
  • POST /billing/resolution-usage-meter/preview — pay-per-resolution metering
  • POST /billing/margin-rollup/preview — reseller margin + revenue share
  • POST /billing/payout-ledger/preview — partner payout ledger + statement
Every one is a pure, read-only estimate. No money moves, no database row is written, no Stripe or Orb event is emitted, and nothing is debited from a wallet. Each is gated by billing-read auth. This page frames them as one projection layer, distinct from the ledger (money that moved) and from the what-if rate simulator (hypothetical rate cards). The worked examples at the end show the two reseller-side projections — a leaf-tenant margin statement and a marketplace builder payout.

Purpose — a projection oracle, not a ledger and not a simulator

Orbit has three forward/backward-looking layers that are easy to confuse: The pricing-preview layer is the middle row: a projection oracle. It reads no live ledger state and writes nothing back. A tenant or reseller posts candidate usage inputs (messages, voice minutes, invocations, resolutions, margin lines, payout entries) and gets back the exact billing breakdown the live engine would compute for those inputs. Read it before enabling a charge path, before paying a partner, or before telling a leaf-tenant what its month will look like.

Input catalog — the six engines each fan-in reads

The preview controller is a fan-in over six billing calculators. Each endpoint composes one of them; reading the controller’s imports is the whole input catalog:
  • resolution-usage-meterprojectResolutionUsageEvents, aggregateResolutionMeter, buildResolutionInvoiceLineItems: projects confirmed AI resolutions into idempotent usage events, rolls them into a meter, see them as line items.
  • margin-rollupcomputeMarginRollup, computeResellerRevenueShareStatement, and the MarginLine / MarginGroup types: rolls reseller lines (revenue, COGS) into sub-account / channel / region margins, and computes a partner revenue-share statement from the same rollup.
  • payout-ledgercomputePartnerPayoutLedger, computePartnerPayoutStatement, and the PayoutLedgerEntry / PayoutLedgerComputedEntry types: folds accrual, payout, and adjustment events into a running balance, then cuts a period statement.
  • marketplace-rev-sharecomputeMarketplaceRevShare, aggregateBuilderPayouts: splits metered marketplace invocations into gross, platform fee, and per-builder payout.
  • aiaas-usage-pricingcomputeAiaasUsageCharges: estimates AI usage across the three billable axes (messages, voice minutes, resolved outcomes).
  • outcome-pricingoutcomePricingConfigSchema: the config schema the resolution-meter preview validates against.
The request-body validation lives in a shared schemas module that reuses each engine’s canonical config schemas, so the preview can never drift from the engine it estimates.

Aggregation envelope — one org-scoped response per endpoint

Each preview endpoint owns one engine’s aggregation and returns one org-scoped JSON envelope. There is no cross-engine summation at the controller layer — each endpoint projects its own shard and returns its own totals inside the standard { data, meta } envelope. Because each response is org-scoped and billing-read-gated, a reseller re-reads only its own branch of the tree, and a tenant re-reads only its own usage. All validation errors return 422 with a single VALIDATION_ERROR code, and margin-preview rejects mixed-currency inputs rather than summing across them — a cross-currency sum would be meaningless.

Reading it — preview vs dashboard calculator vs the real charge path

Use the layer for the question you actually have:
  • “What did I already spend?” — read the wallet ledger or the usage-records feed. The preview never substitutes for the posted record.
  • “What would this month look like?” — post the candidate usage to the relevant preview endpoint and read the projected breakdown.
  • “What if I change the rate?” — use the pricing calculator / what-if simulator, which vary the rate card, not the usage.
The dashboard billing calculator and record simulations layer over the same pure engines the preview endpoints expose — the numbers agree with the projection layer by construction, because both call the same calculators. The real charge path is separate: it consumes posted usage records through the metering pipeline and debits the wallet, and reads none of the preview responses.

Glossary

  • Margin line — one reseller profitability input: a sub-account, channel, optional region, its revenue, and its cost of goods. margin-rollup folds a set of these into margins.
  • Revenue share — a partner’s negotiated percentage (basis points) of the net margin a reseller earned, computed from the same margin rollup so the statement agrees with the rollup.
  • Payout ledger entry — one accrual, payout, or adjustment event on a partner’s ledger, with a running balance after each entry.
  • Projected invoice line item — a line the resolution meter would emit on an invoice if the period closed now; a descriptor, not a posted line.

Worked example — reseller margin + partner revenue share

A reseller projects one leaf-tenant’s month before close and asks for its white-label partner’s statement in the same call.
The abbreviated response rolls totals, per-channel groups, and — because revenue_share was supplied — the partner statement computed from the same rollup:
Reseller reads at a glance: net 48,900 minor units of margin for the leaf, and the partner is owed 25% of that — 12,225.

Worked example — marketplace builder payout projection

A platform projects what it owes marketplace builders before running a payout. It posts metered invocations and per-listing pricing and gets back the gross, the platform fee, and each builder’s payout.
The abbreviated response splits each listing’s gross into platform fee and builder payout, then aggregates builders (here, builder1’s two calls and builder2’s one):
The platform knows before close: it invoices 290,000 total, retains 4,350 as its fee, and owes builder1 236,400 and builder2 49,250.

Boundary — what the projection layer is not

  • Not the ledger. The billing and wallet model and wallets, credits, and charges cover money that moved. A preview never reads or writes the wallet.
  • Not an invoice. Billing documents owns the post-close receivable a provider issues. A preview is pre-close by definition and becomes non-authoritative at close.
  • Not the raw usage feed. Usage metering pipeline owns the raw usage record feed the meters roll. A preview consumes candidate inputs, never the posted feed.
  • Not a rate simulator. The pricing calculator varies the rate card; the preview varies the usage. They answer different “what if” questions.