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

# Revenue recognition

> Straight-line deferred-revenue schedules for committed-use commitments and subscription invoice lines: the schedule and summary endpoints, the model, the dashboard, and month-end use.

# Revenue recognition

Deferred revenue answers one finance question: **how much of what customers
already paid have you actually earned, and how much is still deferred.**
When your account carries a committed-use commitment (a negotiated prepaid
minimum commit) or recurring subscription invoice lines, that money is
received up front but earned over a service window. Until it is earned it
sits on the books as deferred revenue, not recognized revenue.

Orbit turns the contracts you already have into ratable **straight-line
recognition schedules** — the per-month amounts a finance team books under
ASC 606 — computed on demand from your committed-use commitment and your
subscription invoices. Nothing has to be configured: no upload, no schedule
construction, no mapping table.

Two endpoints and one dashboard page cover the whole surface:

* `GET /api/v1/billing/revenue-recognition/schedule` — the per-contract
  recognition schedule, one entry per calendar month.
* `GET /api/v1/billing/revenue-recognition/summary` — the rollup:
  recognized-to-date vs. remaining-deferred as of a reporting date, plus the
  recognized amount in each period.
* **Dashboard → Billing → Revenue recognition** — the same data, read-only.

Everything on this surface is read-only. It moves no money, issues no
charge, and writes no record — each call recomputes the schedule from the
live contract data at request time. Both endpoints require the `owner`,
`admin`, or `billing` role.

***

## 1. What revenue recognition answers

Split every contract's value into two buckets as of a reporting date:

* **Recognized to date** — the share of the contract value earned up to the
  reporting date, prorated straight-line across the service window.
* **Deferred remaining** — the share not yet earned. Still a liability; it
  converts to recognized revenue as the window elapses.

Recognized + deferred always equals the total contract value — the summary
reconciles by construction, so it can tie straight into a deferred-revenue
roll-forward. The **by-period** view then answers the second question — how
much revenue lands in each calendar month — summed across all contracts.

***

## 2. The two endpoints

Both endpoints accept one optional query parameter:

| Parameter | Notes                                                                                                                                                                          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `as_of`   | Reporting date, `YYYY-MM-DD` interpreted as UTC midnight. Omitted → the current time. An invalid value fails closed with a 422 rather than silently picking a surprising date. |

### 2.1 Per-contract schedule

`GET /api/v1/billing/revenue-recognition/schedule` returns one recognition
schedule per contract — your committed-use commitment plus each recognizable
subscription invoice line.

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

```json theme={null}
{
  "data": {
    "currency": "USD",
    "as_of": "2026-08-31T00:00:00.000Z",
    "schedules": [
      {
        "contract_id": "committed-use",
        "source": "committed_use",
        "description": "Committed-use commitment",
        "currency": "USD",
        "total_minor": 1200000,
        "total": "12000.00",
        "service_start": "2026-01-01T00:00:00.000Z",
        "service_end": "2027-01-01T00:00:00.000Z",
        "recognized_to_date_minor": 799561,
        "recognized_to_date": "7995.61",
        "deferred_minor": 400439,
        "deferred": "4004.39",
        "periods": [
          {
            "period": "2026-01",
            "period_start": "2026-01-01T00:00:00.000Z",
            "period_end": "2026-02-01T00:00:00.000Z",
            "amount_minor": 101918,
            "amount": "1019.18"
          }
        ]
      }
    ]
  }
}
```

Top-level fields:

| Field       | Notes                                                                                   |
| ----------- | --------------------------------------------------------------------------------------- |
| `currency`  | ISO 4217 currency of the contracts (fallback `USD`).                                    |
| `as_of`     | The reporting instant the recognized/deferred split was computed against, ISO 8601 UTC. |
| `schedules` | One entry per contract, in source order: committed-use first, then subscription lines.  |

Per-schedule fields:

| Field                                             | Notes                                                                                                                                                    |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contract_id`                                     | Stable identifier: `committed-use` for the commitment, otherwise the originating invoice and its line.                                                   |
| `source`                                          | `committed_use` or `subscription` — the artifact that created the deferred balance.                                                                      |
| `description`                                     | Human label (commitment tag or invoice line name).                                                                                                       |
| `currency`                                        | ISO 4217 currency of that contract.                                                                                                                      |
| `total_minor` / `total`                           | Contract value, in integer cents and as a decimal string. The `*_minor` integer is the exact value; the string is the same amount formatted for display. |
| `service_start` / `service_end`                   | The recognition window. Start inclusive, end exclusive.                                                                                                  |
| `recognized_to_date_minor` / `recognized_to_date` | Earned through `as_of`, prorated straight-line.                                                                                                          |
| `deferred_minor` / `deferred`                     | Still deferred — always `total − recognized_to_date`.                                                                                                    |
| `periods`                                         | Per-calendar-month entries (`YYYY-MM`, UTC) with the recognized amount per month. The entries sum to `total` exactly.                                    |

### 2.2 Recognized-vs-deferred summary

`GET /api/v1/billing/revenue-recognition/summary` rolls every contract up
into org-level totals.

```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"
```

```json theme={null}
{
  "data": {
    "currency": "USD",
    "as_of": "2026-08-31T00:00:00.000Z",
    "contract_count": 2,
    "total_contract_value_minor": 1240000,
    "total_contract_value": "12400.00",
    "recognized_to_date_minor": 803561,
    "recognized_to_date": "8035.61",
    "deferred_remaining_minor": 436439,
    "deferred_remaining": "4364.39",
    "by_period": [
      { "period": "2026-01", "recognized_minor": 105918, "recognized": "1059.18" }
    ]
  }
}
```

| Field                                                 | Notes                                                                                                                                       |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `contract_count`                                      | Number of schedules in the rollup. `0` when nothing is recognizable yet (see limits below).                                                 |
| `total_contract_value_minor` / `total_contract_value` | Whole contract value across all sources.                                                                                                    |
| `recognized_to_date_minor` / `recognized_to_date`     | Earned through `as_of` across all contracts.                                                                                                |
| `deferred_remaining_minor` / `deferred_remaining`     | Still deferred. `recognized_to_date + deferred_remaining = total_contract_value` exactly — that reconciliation is the acceptance guarantee. |
| `by_period`                                           | Recognized amount per calendar month, summed across all contracts, ascending. Its grand total equals the total contract value.              |

***

## 3. The straight-line model

The model is deliberately simple — the same ratable treatment the leading
usage-billing platforms apply:

* **Committed-use commitment.** The total contract value is the monthly
  commit × the number of whole months in the contract term, recognized
  straight-line over the term. When the commitment carries no term dates,
  the schedule falls back to the current billing period — one month
  recognizing the monthly commit — so a schedule always exists.
* **Subscription invoice lines.** Each positive-amount line on a
  subscription invoice recognizes over the line's own service window; when
  the line has none, the window falls back to the invoice's billing period,
  then to 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 any residual cent, so the schedule
never drifts off the invoice amount. Amounts are computed in integer cents,
never floating point.

Assumptions to be aware of:

* The split is prorated to the exact reporting instant — a mid-month
  `as_of` recognizes the elapsed fraction of that month, not the whole
  month.
* Credit and zero-amount invoice lines do not recognize and are excluded.
* The rollup requires one currency; it reports the commitment's currency,
  else the currency of the first subscription line, else `USD`.

***

## 4. Dashboard walkthrough

The same two reads render under **Dashboard → Billing → Revenue
recognition**. The page is read-only — it reflects your contracts; it does
not edit them — and it is gated to the `owner`, `admin`, and `billing`
roles, matching the API.

* **Stat cards** — total contract value, recognized to date, and deferred
  remaining across all contracts.
* **Recognized by period** — the cross-contract table of revenue per
  calendar month.
* **Per-contract schedules** — one card per contract with its source badge
  (Committed-use or Subscription), service dates, recognized/deferred split,
  and the month-by-month schedule table.

Report-date semantics match the API: the page reports as of the current
time. For a historical reporting date, pass `as_of` on the API.

An account with no committed-use commitment and no subscription invoices
sees an empty state explaining when schedules appear — nothing is broken.

***

## 5. Finance-ops use

**Month-end close.** Pull the summary with a fixed `as_of` — e.g.
`as_of=2026-08-31` for the August close — so rerunning the report later
reproduces the same figures instead of rolling with the clock. The
recognized/deferred totals book as the period's recognition entry; because
they reconcile to contract value exactly, the deferred balance rolls forward
without a plug.

**Export.** The JSON responses are stable-schema and integer-exact; pipe
them into your close tooling, or read the same tables in the dashboard and
copy the per-period rows.

Limits and edge cases:

* **Subscription history window.** Subscription lines come from the most
  recent invoice page (up to 50 invoices). Long-lived accounts should treat
  the commitment as the primary multi-year source and the subscription lines
  as the recent-period complement.
* **Commitment without a term.** A commitment with no term dates recognizes
  the monthly commit inside the current billing period — a useful default,
  not a multi-year schedule. Have your Devotel account team set the term for
  the full picture.
* **Subscription lines fail open.** If the billing provider read is
  unavailable, the endpoints still return the committed-use schedule — the
  summary degrades rather than errors.
* **Not a revrec ledger.** The schedule is computed on demand from live
  contract data; renegotiating a commitment restates the whole schedule.
  There is no stored history to drift — the contract is the record.

***

## 6. Related pages

* [Billing overview](/billing/overview) — the wallet, top-ups, invoices,
  commitments, and alerts this surface sits alongside.
* [Billing API reference](/api-reference/billing) — endpoint-by-endpoint
  request/response detail.
* [Committed-use contracts](/billing/overview#7-committed-use-contracts) —
  the drawdown meter; revenue recognition is the deferred-revenue view of
  the same contract.
