> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Pricing and rate resolution: how a per-operator price is attributed

> How Devotel Orbit resolves the SMS price for a per-operator rate-card row — the precedence between a verbatim per-operator override, an organization markup, the platform-default markup, and the no-published-rate case — why the rate card labels the same pricing rule the wallet is actually charged under, and how that resolution threads through the shared send pipeline into the wallet ledger.

# Pricing and rate resolution

[How billing meters your usage](/concepts/billing-and-wallet) 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-operator
`your_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:

1. **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.
2. **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.
3. **The platform-default markup** — when neither override exists, the
   price is the operator cost multiplied by the platform default (20%).
4. **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.

The send path and the display path both run this same precedence. The send
path (packages/billing/src/rate-resolver.ts and
mccmnc-rate-resolver.ts) resolves the price you are charged; the rate card
handler for `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 ordered
`channel_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](/concepts/wallets-credits-and-charges).

### Where usage metering (reseller rating) fits

The Usage Metering API on
[How billing meters your usage](/concepts/billing-and-wallet) 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:

```json theme={null}
{
  "data": [
    {
      "mccmnc": "26201",
      "operator_name": "Deutsche Telekom",
      "country": "Germany",
      "your_rate": 0.075,
      "currency": "USD",
      "pricing_source": "absolute_override"
    }
  ],
  "meta": { "cursor": "26201", "has_more": true }
}
```

The `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.

An operator with no published cost row still appears on the card (it is not
silently dropped) with `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-facing
  `GET /pricing/changelog` route exposes the public projection of that
  log (which rule changed, its scope, and when — never internal cost or
  margin fields), and `pricing-history.ts` derives 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.

Manage the per-operator overrides yourself through
[`POST /api/v1/billing/mccmnc-overrides`](/api-reference/billing)
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 displayed
`pricing_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 `null` source 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_source` is 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](/concepts/wallets-credits-and-charges) —
  the append-only ledger the resolved price debits.
* [How billing meters your usage](/concepts/billing-and-wallet) — the
  wallet, FX, graduated tiers, reseller margin, and tax that sit behind the
  resolved per-unit price.
* [Cross-channel fallback](/concepts/cross-channel-fallback) — how the
  envelope's channel chain walks and re-ranks before a price is ever
  resolved.
* [Billing API reference](/api-reference/billing) — the endpoint schemas for
  balance, ledger, and the per-operator override endpoints.
* [Number lifecycle](/concepts/number-lifecycle) — how monthly rental
  charges (a pricing class separate from per-send ratings) debit the
  wallet.
