Pricing and rate resolution
How billing meters your usage covers the pipeline up to the rated amount — the prepaid wallet, FX on converted top-ups, graduated tiers, reseller margin, and tax. Where that page stops is where this one starts: per-send price attribution — for an SMS priced per destination operator (MCC/MNC), which pricing rule supplied the number you are charged. Read this page when you need to explain a per-operatoryour_rate on the rate card, or to reconcile the rate card against the
ledger.
The rate-resolution precedence
For a given destination operator, Orbit resolves the customer price by consulting rules in a fixed order. The first rule that matches wins:- A per-operator rate override — a negotiated price for your organization on that specific operator. It applies verbatim: no markup is layered on top. This is the strongest rule and beats every markup-based rule, even when a markup override also exists.
- Your organization’s own markup override — when no per-operator override exists but the operator has a published cost, the price is the operator cost multiplied by your organization’s markup.
- The platform-default markup — when neither override exists, the price is the operator cost multiplied by the platform default (20%).
- No published rate — when the operator has no published cost row at all, there is no resolved price. The rate card shows a Contact sales row and nothing is attributable.
GET /pricing/mccmnc-rates
(apps/api/src/routes/pricing/mccmnc-rate-card-source.ts) classifies each row
into absolute_override, org_markup, default_markup, or null using
the same inputs. Because both paths agree, the label on the card names the
rule the wallet is actually billed under.
How rating reaches the send pipeline
Rate resolution is not a side calculation the rate card runs for display — every channel’s send path funnels its charge through the same per-send resolution step, so a price you can read on the rate card is the same price the wallet is debited.One resolution step for every channel
SMS, voice, video, AI tokens, and the usage-metering rollup all resolve their customer price through one shared resolver before any wallet movement happens. Each send passes its channel, destination, and quantity to that step and receives back the full price breakdown: the per-unit price, the quantity multiplier (segments, minutes, tokens), the total charge in your wallet currency, and the attribution labels naming the rule that produced the price. For an SMS send that carries a resolved destination operator (the MCC/MNC pair the network lookup returned), the per-operator precedence above runs first: override verbatim, then operator cost × markup. Only when no operator-level rule matches does the resolution fall through to the generic rate-card ladder — an organization-specific rate row, then the global per-country rate, then the published fallback for that channel.The envelope threads one declaration through the router
Above the resolver, the channel-agnostic message envelope carries your send as a single declaration: one recipient, one content bag (a universal text body plus optional per-channel variants), and an orderedchannel_chain fallback preference. The router walks that chain top-down,
attempts the first channel that has both a provider and a renderable
content variant, and falls through on transient failure. Pricing rides
along unchanged: whichever channel wins the walk is rated through the same
resolution step described above, and its declared channel is what determines
which rate-card ladder and which per-operator rules apply. Setting
costAware: true on the envelope re-ranks your declared chain
cheapest-first using the platform rate card (or your own per-send cost
overrides) before the walk starts — the preference set is yours, the rate
card only re-sequences it.
The resolved price is what lands on the ledger
The charge the resolution computed is the amount debited from your wallet, and the ledger row carries the attribution with it — which rate row, which override, the carrier cost, the markup applied, and the FX leg when your wallet currency differs from the pricing currency. That is what makes the reconciliation loop closed: a ledger debit can be traced back to the exact pricing rule that produced it, and the message record exposes that attribution so a message charged on the generic fallback is never rendered as if a per-operator rate had resolved. How balance, ledger, and debits behave once the price is resolved is the subject of Wallets, credits, and charges.Where usage metering (reseller rating) fits
The Usage Metering API on How billing meters your usage is a reseller-facing rating surface: you POST your own subaccounts’ usage events with a meter definition (unit, included quantity, graduated tiers) and receive a rated rollup you can mark up and invoice to your end customers. It is deliberately stateless — it previews the debit descriptors rather than moving money. It does not re-run the per-operator resolution on this page: it rates the quantities you supply against the meter you define. Orbit’s own real-time debits — the ones that appear in your wallet ledger — all resolve through the single per-send step above, and only those debits ever touch your wallet.What the per-operator rate card shows
GET /api/v1/pricing/mccmnc-rates returns one row per operator: the
operator code, operator name, country, your your_rate, its currency, and
a pricing_source label:
pricing_source label is exactly one of the precedence outcomes:
absolute_override— a per-operator override was applied verbatim.org_markup— operator cost × your organization’s markup.default_markup— operator cost × the platform default.null— no published rate; the row is Contact sales, not a price.
your_rate: null and pricing_source: null. Treat
that row as “no published rate” — it is never a signal that sending is
free. In the dashboard, this same card renders under Billing → SMS rates.
How overrides persist
Three tables hold the state that the resolver reads:mccmncRateOverrides— a per-(organization, operator) rate override, applied verbatim (absolute_override).orgPricingOverrides— the organization-wide markup override (org_markup).pricingChangeLog— the append-only audit table. Every write to an override or a rate row records the before and after state, so every change of a pricing rule is journal-traceable. The tenant-facingGET /pricing/changelogroute exposes the public projection of that log (which rule changed, its scope, and when — never internal cost or margin fields), andpricing-history.tsderives the same history for rate rows that were seeded without a recorded entry, so the audit view reflects the full rate card’s provenance rather than only later API mutations.
POST /api/v1/billing/mccmnc-overrides
and the sibling list/update endpoints on that page. Organization-wide
markup overrides are set by the platform on your organization.
Display matches charge — the one invariant
The rate card is not decorative. For every row it shows, the displayedpricing_source names the same pricing rule the send path charges you
under. The recorded error case this invariant guards against is a card
attributed to one rule (for example a 0.01 display rate) while the wallet
was charged under another (a 0.075 actual charge); that misattribution is
what the display-vs-charge check exists to catch. Two consequences for
reading the card:
- A
nullsource row is not a price. It means no published rate exists for that operator. Never treat it as a zero cost, and never quote it to your own customers as a rate. - A labeled row is authoritative. When
pricing_sourceis non-null, the same rule produced the charge in the ledger, so you can attribute a debit to the override, your markup, or the default with confidence.
Related pages
- Wallets, credits, and charges — the append-only ledger the resolved price debits.
- How billing meters your usage — the wallet, FX, graduated tiers, reseller margin, and tax that sit behind the resolved per-unit price.
- Cross-channel fallback — how the envelope’s channel chain walks and re-ranks before a price is ever resolved.
- Billing API reference — the endpoint schemas for balance, ledger, and the per-operator override endpoints.
- Number lifecycle — how monthly rental charges (a pricing class separate from per-send ratings) debit the wallet.