> ## 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.

# Volume tiers and revenue recognition: the finance-ops workflow

> Model a rate change against your own traffic with the what-if simulator, set volume-tier alerts before a drop, then run the monthly close: statements, recognition, pay-by-link accrual, and export to your ERP.

# Volume tiers and revenue recognition

Two console pages sit at the heart of the finance-ops workflow — the
**Volume tiers** page (`/billing/volume-tiers`) and the **Revenue
recognition** page (`/billing/revenue-recognition`). One discounts the
usage you forecast; the other turns the money you already collected into
recognized revenue your ERP can post. This guide walks through both halves
end-to-end and closes with a month-end close you can reproduce.

The audience is **RevOps and Finance admins** — the roles that own the rate
card and the ledger. Every surface referenced below is gated to the same
`owner`, `admin`, or `billing` roles.

### Part A — Volume tiers

## 1. What a volume tier is

A volume tier is a band in a progressive discount ladder: pass a monthly
usage threshold and the per-unit price for that channel drops, in real time,
for every subsequent send. Two kinds of tiers participate:

* **Platform-default tiers** — Devotel's own ladder for the channel, visible
  to every tenant until you override it.
* **Your negotiated tiers** — rows private to your organization, created
  under **Billing → Volume tiers** (`/billing/volume-tiers`) by an
  `owner` or `admin`. They win over the defaults and price until you remove
  them.

The dashboard groups the ladder per channel (`sms`, `whatsapp`,
`voice_minutes`, plus a country override when the row is set) so you can
compare your private rates against the defaults at a glance. The same
`GET /api/v1/billing/volume-tiers` endpoint backs the page — the only
difference is which rows you see there.

The preview endpoint
`GET /api/v1/billing/volume-tier-preview?channel=sms&projected_volume=250000`
backs the inference in the page: given a projected monthly volume it returns
the ladder that applies, the per-unit price it earns, and the projected
savings versus the undiscounted rack rate.

## 2. Model a new SKU before it ships

The **What-if pricing simulator** (`/billing/simulator`) replays your own
recorded traffic through a candidate rate card over a 1–90 day look-back and
returns the per-lane cost delta. It is the safest surface for the
question "what would this tier structure have cost" because the simulator
holds your actual usage fixed and flips only the rates.

To model a new SKU — say a tiered SMS structure where 100k messages bill at
0.8¢ per message and 1M messages bill at 0.64¢ — run it as a candidate card
row through the simulator:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/billing/whatif-pricing/preview" \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "window_days": 30,
    "label": "SMS tiers 100k vs 1M",
    "candidate_card": [
      {
        "channel": "sms",
        "country_code": "*",
        "direction": "mt",
        "rate_per_unit": 0.008
      },
      {
        "channel": "sms",
        "country_code": "US",
        "direction": "mt",
        "rate_per_unit": 0.0064
      }
    ]
  }'
```

Run it twice — once for each breakpoint — and read the totals. The
simulator's `delta_cents` against your current spend is the exact price
break a tier buy-in earns you. Compare against the
`GET /billing/volume-tier-preview` savings line to see whether the tier
math on your own mix matches what the simulator predicts.

Because the simulator replays the traffic you already sent, the lanes it
matches tell you the real coverage: if `candidate_matched` is `false` on the
bulk of your traffic the tier structure you designed is priced on too few
lanes to be meaningful. The simulator never writes anything; a preview is
read-only.

## 3. Alert before you drop to a worse tier

A volume tier is a month-level commitment: when traffic slips below the
breakpoint you silently fall back to a worse per-unit price without any
warning. Two tripwires catch that slide before month-end:

* **Usage-anomaly alert rules** — the console raises an alert on any
  traffic-velocity drop against your own historical baseline. See
  [Usage anomaly alert rules](/guides/usage-anomaly-alert-rules) for the
  rule grammar.
* **Cost-intelligence dashboards** — track the per-channel unit-cost trend
  over the trailing days; a rising average per unit is the earliest sign of
  a missed breakpoint. See [Cost intelligence](/guides/cost-intelligence).

Pair either tripwire with the page's **Billing → Alerts** threshold badges
so the right people get notified before the tier rolls back.

### Part B — Revenue recognition

## 4. The recognition model

Revenue recognition answers one ledger question: **how much of what
customers already paid have you actually earned.** When your account carries
a committed-use commitment or a subscription invoice line, the money arrives
upfront but is earned across a service window; until it is earned it sits
on the books as deferred revenue.

Orbit turns those contracts into ratable **straight-line recognition
schedules** — the per-month amounts a finance team books under ASC 606 —
computed on demand from the contract data at request time. The model is
documented endpoint-by-endpoint in
[Revenue recognition](/billing/revenue-recognition). Read that page first
for the field definitions; this section adds the month-end workflow.

* **Committed-use commitment.** The total contract value is the monthly
  commit × the whole months in the term, recognized straight-line over the
  term. When the commitment carries no term dates the schedule falls back to
  the current billing period, so a schedule always exists.
* **Subscription invoice lines.** Each positive-amount line recognizes over
  its own service window; when the line has none the window falls back to
  the invoice's billing period, then the invoice-date month.

Recognition within a window is **straight-line by day**: each month
recognizes a share proportional to the number of window days inside it, so
February earns less than January in a flat-rate schedule. A cumulative
rounding method keeps the period entries summing to the contract total
exactly — the final period absorbs the residual cent. The schedule is
read-only; each call recomputes from live contract data.

## 5. Journal the internal-code mapping

The two endpoints —
`GET /api/v1/billing/revenue-recognition/schedule` and
`GET /api/v1/billing/revenue-recognition/summary` — return a stable schema
your finance team maps to the chart of accounts once and posts from every
month thereafter. Both require the `owner`, `admin`, or `billing` role.

Per contract, the schedule reply carries an attribution chain. Map the
fields into your journal template:

| Reply field                       | Journal use                                                                            |
| --------------------------------- | -------------------------------------------------------------------------------------- |
| `contract_id`                     | Internal code — `committed-use` for commitment, else the originating invoice and line. |
| `source`                          | Bucket: `committed_use` or `subscription`.                                             |
| `description`                     | Human label (commitment tag or invoice line name).                                     |
| `currency`                        | ISO 4217 currency of the contract.                                                     |
| `service_start` / `service_end`   | Recognition window, start inclusive / end exclusive.                                   |
| `recognized_to_date` / `deferred` | Earned through `as_of` versus still deferred.                                          |
| `periods`                         | Per-calendar-month entries that sum to the total exactly.                              |

The summary reply rolls every contract up into recognized-to-date versus
deferred-remaining totals plus a by-period rollup — the same reconciliation
math a deferred-revenue roll-forward uses.

## 6. Connecting to ERP connectors

The ERP connector setup lives under **Developer → Connectors**
(`/developer/connectors`), a per-tenant page that generates a deterministic
app-definition JSON pre-wired to your API host — the Zapier Platform CLI
config, the Make custom app, or the `n8n-nodes-orbit` community node pack.
Import it into the integration tool of your choice and authenticate with
your own API key after connection.

Once the connector is live, add a schedule-driven job that polls the
summary endpoint with a fixed reporting date for the month you are closing:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/billing/revenue-recognition/summary?as_of=2026-08-31" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Because the reply schema is stable and the amounts are exact, the connector
can post the recognized/deferred totals to your general-ledger connector
endpoint without any mapping logic changes between runs. Use the
`/developer/connectors` download the moment before the first close so the
file path, API key, and tenant host are wired together.

## 7. A monthly close sample

A clean close sequence for the August close, run by a Finance admin:

1. **Pull the fixed reporting date.** Call the summary endpoint with
   `as_of=2026-08-31` — the fixed date keeps reruns of the close pinned to
   the same figures.
2. **Journal the split.** Post the `recognized_to_date` and
   `deferred_remaining` totals from the summary into your ERP journal using
   the contract-to-internal-code mapping from section 5.
3. **Catch the unbilled pay-by-link accrual.** A payment link still awaiting
   collection is accrued revenue on the ledger even though no wallet
   statement exists yet; the statements list (`/billing/statements`) skips
   it, so treat it as an accrual entry, and only recognize the invoice once
   the payment settles — see the
   [Pay by link](/billing/overview#2-top-up-flows) surface for collection
   status.
4. **Anchor the reporting view.** Because the dashboard's recognition page
   already reflects your contracts as of the current time, read it over the
   same window you posted in step 2 and confirm the two match.
5. **Confirm the statement window.** The statements list up to 60 months is
   authoritative for the same period; reconcile the recognition period's
   recognized-to-date total against the wallet's closing balance from the
   statement to rule out orphan ledger drift.

### Cross-cutting notes

* **Role consistency** — the console pages, the simulator, the preview
  endpoint, and the recognition endpoints are all gated to the same
  `owner`, `admin`, or `billing` role. A Finance member who needs only the
  dashboard can be elevated accordingly by the organization owner.
* **Tenant-owned controls** — journal mapping, ERP connector authentication,
  and tier overrides are tenant-owned; the recognition schedule itself is a
  read-only, computed-on-demand view.
* **Rate-resolution** — volume-tier discounts sit alongside the same
  pricing-resolution ladder your invoice uses; see
  [Pricing and rate resolution](/concepts/pricing-rate-resolution) for how
  per-operator rates interact with the tier override.

## Related

* [Revenue recognition](/billing/revenue-recognition) — the per-period
  schedule and summary semantics in full.
* [Billing overview](/billing/overview) — the wallet, statements,
  committed-use contracts, and pay-by-link collection.
* [What-if pricing simulator](/guides/whatif-pricing-simulator) — the
  deeper guide on candidate-lane replay.
* [Cost intelligence](/guides/cost-intelligence) — per-channel unit-cost
  trend reading against a tier slide.
* [Usage anomaly alert rules](/guides/usage-anomaly-alert-rules) —
  traffic-velocity alerting before a tier drop.
* [Pricing and rate resolution](/concepts/pricing-rate-resolution) —
  how a per-operator price is attributed alongside the tier override.
