# Monthly revenue & unbilled usage

Every subscription read returns `monthlyRevenue`: what the subscription bills
per month today. Metered consumption is not part of that figure, so a separate
endpoint returns the usage recorded so far in the current billing period. Use
the two together to report MRR and to estimate the next invoice.

## `monthlyRevenue`

`GET /v1/subscriptions` and `GET /v1/subscriptions/{id}` return
`monthlyRevenue` (a decimal string), `currency` and `hasMeteredProducts`. Each
add-on in a subscription's `addons` array carries its own `monthlyRevenue`.

```json
{
  "id": "019F3C59-7988-7264-82D7-EB456918ED02",
  "status": "ACTIVE",
  "currency": "DKK",
  "monthlyRevenue": "15000.00",
  "hasMeteredProducts": true
}
```

| Question | Answer |
|---|---|
| Is VAT included? | No. The figure is computed from the same net line amounts an invoice adds VAT to. |
| Is it per month when billed quarterly or yearly? | Yes. Each billing interval is converted to one month: a quarter is divided by 3, half a year by 6, a year by 12, and weekly prices are multiplied by 52/12. |
| Are discounts applied? | Yes. Plan discounts, interval discounts and recurring surcharges are applied. |
| Are one-off charges included? | No. A setup fee or other one-off charge is billed once. |
| Are add-ons included? | No. Each add-on is its own subscription with its own `monthlyRevenue` and appears as its own row in the list. The invoice a parent sends carries its own figure plus its add-ons', so adding up every subscription counts nothing twice. |
| Is usage-based consumption included? | No, because it is not known until the period closes. A metered line counts only through a prepaid commitment (the committed quantity at its committed price) or a fee its price charges at zero usage. Read [unbilled usage](#unbilled-usage) for the rest. `hasMeteredProducts` says whether the subscription has a metered product. |
| Which date does it describe? | Today. A change scheduled for a later date shows from the day it takes effect. |
| Does a catalog price change move it? | Not by itself. A running subscription keeps billing the price it has. When a change to the subscription takes effect, its lines bill at the catalog price of that day, except a line with a negotiated price, which bills that price. |
| What during a trial? | The price billing starts at when the trial ends. |
| What before the start date or after the end? | `0.00`. A migrated subscription that was already billing in another system counts from its original start date. |

`monthlyRevenue` is in the subscription's `currency`, the currency it is
invoiced in. Convert to one currency before summing subscriptions in different
currencies.

## Unbilled usage

`GET /v1/subscriptions/{id}/usage` returns the usage the subscription has
recorded but not yet been invoiced for, one entry per metered price and billing
period.

```bash
curl 'https://api.ledgerbee.com/api/v1/subscriptions/019F3C59-7988-7264-82D7-EB456918ED02/usage' \
  -H 'x-api-key: <your-key>'
```

```json
{
  "subscriptionId": "019F3C59-7988-7264-82D7-EB456918ED02",
  "currency": "DKK",
  "lines": [
    {
      "meterId": "0197A943-2325-7829-B835-B6C71A293065",
      "meterName": "Booking revenue",
      "priceId": "0197A943-5A11-7A2C-9F32-1D0C55A7E101",
      "productName": "Commission",
      "periodStart": "2026-10-01",
      "periodEnd": "2026-11-01",
      "quantity": 15000,
      "amount": "4950.00",
      "quantityIsShared": false
    }
  ]
}
```

Usage is billed in arrears. A period's usage is invoiced when the period
closes, on `periodEnd`; until then `amount` grows as usage is reported.
`amount` is priced the way that invoice will price it:

- at the price the subscription is locked to, tiers included;
- excluding VAT;
- before plan and interval discounts, which appear on the invoice as their own
  lines;
- without usage that has already been invoiced;
- without usage recorded before a date you chose not to bill from.

For a line with a [prepaid commitment](/guides/subscriptions/usage-commitments),
`amount` is only the settlement: the usage above what was prepaid, or, when the
commitment refunds unused units, a negative amount for what was not used. The
prepaid commitment itself is part of `monthlyRevenue`, so the two never count
the same money.

Usage is recorded per customer and meter, not per subscription. When another
line bills the same meter (another price on this subscription, or another of
the customer's subscriptions), it reports the same units and
`quantityIsShared` is `true`. Amounts on such lines add up; quantities do not.

Pass `asOf=YYYY-MM-DD` to choose which billing period is current. A
subscription that is behind on billing can return more than one period for one
price. A subscription without metered products returns an empty `lines` array.

Reading usage needs the `subscriptions-read` scope and the Subscription
license. Reporting it is described in
[Reporting usage](/guides/subscriptions/reporting-usage). The full response
schema is in the [API Reference](/api).

## Price changes by webhook

`subscription.started` carries the `monthlyRevenue` and `currency` the
subscription starts at. `subscription.transitioned` carries the figure the
subscription bills after the change, and `effectiveDate`:

```json
{
  "subscriptionId": "019F3C59-7988-7264-82D7-EB456918ED02",
  "transitionType": "plan_replaced",
  "transitionedAt": "2026-10-01T09:14:02.511Z",
  "effectiveDate": "2026-11-01",
  "monthlyRevenue": "18000.00",
  "currency": "DKK"
}
```

`transitionedAt` is when the change was made. For a change scheduled for a
later date it comes before `effectiveDate`; keep the current figure until that
date. On `effectiveDate` a `phase_changed` transition follows when the change
alters the monthly revenue or the entitlements. A change that takes effect the
day it is made sends one event.

A catalog price change sends no event by itself. For a change scheduled for a
later date, `monthlyRevenue` prices a line with no negotiated price at the
catalog price of the day the change was made. That line's price is set on
`effectiveDate`, and `phase_changed` carries the resulting figure when it differs
from what the subscription billed until then.

`monthlyRevenue` on a webhook is `null` only when the subscription could not be
priced; read the subscription to recover the figure. The full payloads are in
[Webhooks](/guides/webhooks), and reconciliation is in
[Webhooks & reconciliation](/guides/subscriptions/webhooks).

## Errors & failure states

| What you observe | Cause | What to do |
|---|---|---|
| `404 SUBSCRIPTION_CUSTOMER_SUBSCRIPTION_NOT_FOUND` | The id is not a subscription of the company the key belongs to | Use the stable `id` from the subscription list |
| `400` validation error on `asOf` | `asOf` is not a real `YYYY-MM-DD` date | Send a calendar date, e.g. `2026-10-01` |
| `403` with `LICENSE.REQUIRED` | Your company does not hold the Subscription license | See [Licenses](/guides/licenses) |
| `monthlyRevenue` is `0.00` on an active subscription | Every product is metered and none has a commitment or standing fee | Read the usage endpoint |
| `quantity` is higher than this subscription's usage | `quantityIsShared` is `true`: another line bills the same meter | Add up `amount`, not `quantity` |
