What-if pricing simulator
Orbit’s what-if pricing simulator answers one operator question: what would this rate card have cost on the traffic I already sent. You pick a look-back window, model a candidate rate card, and the simulator replays your own recorded usage through it — per channel, destination country, direction, and message sub-type — and returns the exact cost delta versus what you paid under your live rates. The traffic is held fixed; only the rates change. Use it to back-test a negotiated sheet, a new plan, or a competitor’s published rates before you commit. Two ways in, same engine:- Dashboard — Billing → What-if pricing simulator (
/billing/simulator) is the interactive surface: pick a window, drag a global ±% adjustment, or type a per-channel rate, and read the projected spend. - API —
POST /api/v1/billing/whatif-pricing/previewis the programmatic path when you need per-country, per-direction, or per-sub-type granularity, or want to run comparisons from your own tooling.
owner, admin, or billing role — the same gate as the other billing surfaces, because the reply carries your real per-channel spend.
1. What the simulator does
A preview run has three steps, all read-only:- Aggregate your usage. The usage events your own organization recorded over the look-back window (1–90 days) are grouped into billing lanes: channel × country code × direction (
mtoutbound,moinbound) × sub-type, with quantities summed per lane. - Price the baseline. Each lane is priced under your current live rates with the same pricing resolver that produces your invoice — the number on the bill and the number in the simulator come from the same math.
- Replay the candidate. Every lane is re-priced through your candidate rate card, and the reply reports the per-lane and rolled-up delta between the two.
2. Where it lives
Open Billing → What-if pricing simulator in the dashboard. The page is role-gated toowner, admin, and billing, matching the gate on the sibling billing drill-downs.
The page has two input groups:
- Traffic window —
24h,7d,30d, or90d. This maps to awindow_daysof 1, 7, 30, or 90 on the API. - Adjustments — one global slider (
−50%to+50%) applied across every channel, plus an editable candidate rate per channel row. A typed rate overrides that channel and ignores the global slider; channels you do not touch follow the slider.
3. Reading a what-if preview
Every reply — dashboard row or API lane — is a current-vs-candidate comparison:
All money fields are in USD cents. Unit prices carry sub-cent precision; totals are whole cents, rounded up once per lane (the never-under-bill convention your invoice also uses).
A candidate row prices a lane through the same ladder your live rates use:
rate_per_unit— wholesale base, USD per unit (per message, or per voice minute).markup_bps— proportional markup in basis points (500= 5%), layered on the base.markup_fixed_cents— flat markup added per unit, in cents.absolute_price_cents— a fixed per-unit price in cents. When set, it wins over the base-plus-markup math entirely.
* wildcard; within that, an exact sub-type match beats a sub-type-agnostic row. Direction must match too — an mt row never re-prices an mo lane.
Dashboard vs API granularity
The dashboard models one rate per channel: a typed rate is sent as a wildcard (*) mt row for that channel, and the result is rolled up to one table row per channel. Two consequences to know:
- Outbound-only. A typed dashboard rate re-prices
mt(outbound) lanes only; inbound lanes keep their current cost. To modelmopricing, use the API withdirection: "mo". - Truly global. The wildcard row re-prices the channel across every destination and sub-type uniformly. To model per-country or per-sub-type pricing (e.g. WhatsApp
marketingvsutilityto Nigeria), use the API with explicitcountry_code/sub_typerows.
4. The API
POST /api/v1/billing/whatif-pricing/preview — requires the owner, admin, or billing role.
The card is a partial override: lanes with no matching row keep their current cost and report
candidate_matched: false with zero delta. You only model the lanes you intend to change.
candidate_matched: false is traffic the candidate card does not price — those lanes stay at current cost in your totals, so a card that covers only part of your mix understates its own impact. matched_lane_count against lane_count in totals tells you the coverage at a glance.
5. Limits and the read-only guarantee
The simulator is a compute surface, safe to run as often as you like:- Nothing changes. A preview writes no record, emits no billing event, and moves no money. Your live rates, your pricing overrides, and your invoice are untouched no matter what you model.
- Window caps.
window_daysis bounded at 1–90 days; the dashboard offers 1, 7, 30, and 90. Replies cover up to 200 distinct lanes (the largest by quantity first), and a single request accepts up to 5000 candidate rows. - A projection, not a forecast. The replay holds your recorded traffic fixed and changes only the rates. Final invoices still vary with delivery outcomes and any negotiated overrides on your account.
/billing/rate-cards): those cells ask “what would one unit cost at this price under this card?” and are instant lookups against a card’s rows. The simulator asks “what would my last 90 days have cost under this card?” and re-prices your real usage lane by lane. For the rate-card library itself, see Rate cards.
6. Worked scenario — price WhatsApp to Nigeria +5%
Model a +5% markup on outbound WhatsApp to Nigeria over the last 30 days, the way a negotiated volume sheet would quote it:- Send the candidate card as one row:
channel: "whatsapp",country_code: "NG",direction: "mt", your wholesalerate_per_unit, andmarkup_bps: 500.
- Read the per-lane results. With no
sub_typeon the row, it re-prices every outbound WhatsApp-to-Nigeria lane —marketing,utility, and untyped traffic alike — so the WhatsApp/NG lanes showcandidate_matched: truewith the +5% delta. To price sub-types differently, send one row per sub-type (e.g.marketingat 500 bps,utilityat 200 bps); the exact sub-type match wins per lane. - Read
totals.delta_centsanddelta_percentare the whole-window impact of the change on your mix;matched_lane_countconfirms the card actually covered the Nigeria lanes you intended, and every other channel’s lanes show zero delta.
30d and type a candidate rate in the WhatsApp row. That models the * wildcard across all destinations, so use the API when the question is country- or sub-type-specific, as above.
Related
- Billing API reference — What-if pricing preview — full request/response field list.
- Rate cards — the rate-card library and per-card pricing cells.
- Billing overview — wallet, charges, and how lanes become line items.