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

# Reseller Usage Metering API

> Meter your own end customers on top of Orbit: rate a batch of usage events against a custom meter and get back a per-subaccount rollup plus a branded, ready-to-send HTML invoice.

# Reseller Usage Metering API

For platforms reselling Orbit to their own customers — agencies, MSPs, vertical SaaS. Send a batch of your end customers' usage events with a custom meter definition, and get back a rated, per-subaccount rollup plus the wallet-ledger and invoice draft you would bill each subaccount with.

This is a **programmatic partner endpoint**: you already hold your end customers' usage events in your own system, so you POST them here and get the rated result back. It is stateless — nothing is persisted and no wallet or invoice is charged. Use it to rate a billing period, preview the numbers, and (optionally) render the branded invoice you hand your customer.

**Base path:** `/api/v1/usage/meters`

**Authentication:** Organization session JWT or an owner/admin API key. You only ever rate your own payload.

## Rate a batch

### Rollup usage events

`POST /api/v1/usage/meters/rollup`

Rate a batch of metered events against a custom meter and return the rollup. Each event names the subaccount that incurred it and a quantity; the meter defines the included quantity and the graduated overage tiers used to price the overflow.

#### Meter definition

| Field              | Type   | Notes                                                                                                                    |
| ------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------ |
| `slug`             | string | `lower_snake_case`, 1–64 chars                                                                                           |
| `displayName`      | string | Human label for the meter                                                                                                |
| `unit`             | string | Unit the quantity is counted in (e.g. `messages`)                                                                        |
| `currency`         | string | ISO-4217 code (e.g. `USD`)                                                                                               |
| `includedQuantity` | number | Units bundled at no charge before overage                                                                                |
| `overageTiers`     | array  | Graduated tiers `{ upTo, unitPriceMinor }`; `upTo` must strictly increase and the last tier is open-ended (`upTo: null`) |

#### Request body

| Field               | Type   | Notes                                                                                                 |
| ------------------- | ------ | ----------------------------------------------------------------------------------------------------- |
| `meter`             | object | The meter definition above (required)                                                                 |
| `events`            | array  | 1–1000 events: `{ subaccountId, quantity, idempotencyKey?, timestamp?, properties? }`                 |
| `period`            | object | Optional `{ start, end }` ISO-8601 rating window, stamped into the ledger/invoice references          |
| `resellerMarginPct` | number | Optional markup `0–100` applied to each subaccount's rated amount (omit or `0` bills at cost)         |
| `tax`               | object | Optional `{ rate_pct, label? }` VAT/GST resolved for the bill-to party; applied to the invoice totals |
| `invoice`           | object | Optional invoice metadata — when present, the response adds a branded HTML invoice (see below)        |

#### Invoice metadata

Supply the optional `invoice` block to also receive a branded, standalone HTML invoice (`billing.invoice.rendered_html`) for the marked-up draft — the document you hand your end customer.

| Field            | Type    | Notes                                                                                                                                                                                               |
| ---------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invoice_number` | string  | Your invoice number                                                                                                                                                                                 |
| `issue_date`     | string  | ISO-8601 date; reduced to a calendar date on the document                                                                                                                                           |
| `due_date`       | string  | Optional payment due date                                                                                                                                                                           |
| `bill_to`        | object  | `{ name, address_lines?, email? }`                                                                                                                                                                  |
| `notes`          | string  | Optional free-text footer                                                                                                                                                                           |
| `branding`       | object  | Optional white-label `{ dashboard_name, logo_url, primary_color, accent_color, support_email, terms_url, privacy_url }` — colors and URLs are validated, with clean platform defaults as a fallback |
| `cost_center`    | string  | Optional chargeback tag printed on the statement                                                                                                                                                    |
| `itemize_fees`   | boolean | When `true`, each line and the totals split into the carrier pass-through cost and your margin                                                                                                      |

<RequestExample>
  ```bash theme={null}
  curl -X POST https://api.orbit.devotel.io/api/v1/usage/meters/rollup \
    -H "X-API-Key: dv_live_sk_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "meter": {
        "slug": "outbound_sms",
        "displayName": "Outbound SMS",
        "unit": "messages",
        "currency": "USD",
        "includedQuantity": 1000,
        "overageTiers": [
          { "upTo": 10000, "unitPriceMinor": 0.8 },
          { "upTo": null, "unitPriceMinor": 0.6 }
        ]
      },
      "events": [
        { "subaccountId": "sub_acme", "quantity": 5200 },
        { "subaccountId": "sub_globex", "quantity": 800 }
      ],
      "period": { "start": "2026-06-01T00:00:00Z", "end": "2026-06-30T23:59:59Z" },
      "resellerMarginPct": 20,
      "invoice": {
        "invoice_number": "INV-2026-06-0042",
        "issue_date": "2026-07-01",
        "bill_to": { "name": "Acme LLC", "email": "ap@acme.example" },
        "cost_center": "growth-emea",
        "itemize_fees": true
      }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "meter": "outbound_sms",
      "currency": "USD",
      "event_count": 2,
      "total": {
        "total_quantity": 6000,
        "included_quantity": 1000,
        "billable_quantity": 5000,
        "amount_minor": 4000,
        "currency": "USD",
        "tiers": [
          { "from_unit": 0, "up_to": 10000, "units": 5000, "unit_price_minor": 0.8, "amount_minor": 4000 }
        ]
      },
      "by_subaccount": [
        {
          "subaccount_id": "sub_acme",
          "event_count": 1,
          "rated": { "total_quantity": 5200, "included_quantity": 1000, "billable_quantity": 4200, "amount_minor": 3360, "currency": "USD", "tiers": [] }
        },
        {
          "subaccount_id": "sub_globex",
          "event_count": 1,
          "rated": { "total_quantity": 800, "included_quantity": 1000, "billable_quantity": 0, "amount_minor": 0, "currency": "USD", "tiers": [] }
        }
      ],
      "billing": {
        "meter": "outbound_sms",
        "currency": "USD",
        "reseller_margin_pct": 20,
        "ledger_entries": [
          { "subaccount_id": "sub_acme", "meter_slug": "outbound_sms", "amount_minor": 4032, "base_amount_minor": 3360, "currency": "USD", "billable_quantity": 4200, "reference": "meter:outbound_sms:sub_acme" }
        ],
        "invoice": {
          "currency": "USD",
          "line_items": [
            { "subaccount_id": "sub_acme", "meter_slug": "outbound_sms", "description": "Outbound SMS", "quantity": 4200, "amount_minor": 4032, "base_amount_minor": 3360, "tiers": [] }
          ],
          "subtotal_minor": 4032,
          "base_subtotal_minor": 3360,
          "total_minor": 4032,
          "rendered_html": "<!doctype html>…"
        }
      }
    },
    "meta": {
      "request_id": "req_rollup_001",
      "timestamp": "2026-07-01T12:00:00Z"
    }
  }
  ```
</ResponseExample>

<Note>
  All amounts are in minor currency units (cents). The `billing` block is a preview of the write descriptors — the wallet-ledger debits and the invoice draft you would charge each subaccount with. This endpoint does not commit them; persisting the ledger and invoice writes is a separate step in your own billing flow.
</Note>

## Issue a credit note

### Credit a prior charge

`POST /api/v1/usage/meters/credit-note`

Issue a credit note (credit memo) or a manual invoice adjustment against a charge you already billed a downstream customer. A credit note reduces what the customer owes on their invoice — use it for an overbilled line, a goodwill credit, a negotiated discount, or a billing-error correction. Unlike a Stripe refund it moves no money on a card; it produces the finance document you hand your customer.

Like the rollup endpoint it is stateless — nothing is persisted. It returns the credited totals and, when you supply a `credit_note` block, a branded, standalone HTML credit note (`credit_note.rendered_html`).

#### Request body

| Field                  | Type   | Notes                                                                                                                                                            |
| ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `currency`             | string | ISO-4217 code (e.g. `USD`)                                                                                                                                       |
| `lines`                | array  | 1–200 credit lines: `{ description, quantity?, amount_minor }`. `amount_minor` is the positive amount credited back on that line                                 |
| `reason`               | string | Optional reason printed on the document                                                                                                                          |
| `tax`                  | object | Optional `{ rate_pct, label? }` — supply the same rate the original invoice used so the tax component is credited too                                            |
| `original_total_minor` | number | Optional tax-inclusive total of the invoice being credited. When supplied, a credit whose total exceeds it is rejected — you cannot credit more than you charged |
| `credit_note`          | object | Optional document metadata — when present, the response adds a branded HTML credit note (see below)                                                              |

#### Credit-note metadata

| Field                     | Type   | Notes                                                                                    |
| ------------------------- | ------ | ---------------------------------------------------------------------------------------- |
| `credit_note_number`      | string | Your credit-note number                                                                  |
| `issue_date`              | string | ISO-8601 date; reduced to a calendar date on the document                                |
| `original_invoice_number` | string | Optional invoice this note credits, shown as an "Against invoice" row                    |
| `bill_to`                 | object | `{ name, address_lines?, email? }`                                                       |
| `notes`                   | string | Optional free-text footer                                                                |
| `branding`                | object | Optional white-label branding, same shape and validation as the invoice `branding` above |

<RequestExample>
  ```bash theme={null}
  curl -X POST https://api.orbit.devotel.io/api/v1/usage/meters/credit-note \
    -H "X-API-Key: dv_live_sk_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "currency": "USD",
      "lines": [
        { "description": "Overbilled outbound SMS", "quantity": 500, "amount_minor": 1200 },
        { "description": "Goodwill credit", "amount_minor": 800 }
      ],
      "reason": "Duplicate charge in June",
      "tax": { "rate_pct": 20, "label": "VAT" },
      "original_total_minor": 4032,
      "credit_note": {
        "credit_note_number": "CN-2026-06-0007",
        "issue_date": "2026-07-01",
        "original_invoice_number": "INV-2026-06-0042",
        "bill_to": { "name": "Acme LLC", "email": "ap@acme.example" }
      }
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "credit_note": {
        "currency": "USD",
        "lines": [
          { "description": "Overbilled outbound SMS", "quantity": 500, "amount_minor": 1200 },
          { "description": "Goodwill credit", "quantity": 1, "amount_minor": 800 }
        ],
        "subtotal_minor": 2000,
        "tax_minor": 400,
        "tax_rate_pct": 20,
        "tax_label": "VAT",
        "total_minor": 2400,
        "reason": "Duplicate charge in June",
        "rendered_html": "<!doctype html>…"
      }
    },
    "meta": {
      "request_id": "req_credit_note_001",
      "timestamp": "2026-07-01T12:00:00Z"
    }
  }
  ```
</ResponseExample>

<Note>
  Amounts are in minor currency units (cents), and the totals are the credited (owed-back) figures. This endpoint does not persist the credit note or apply it to a wallet — record it and apply it against the invoice in your own billing flow.
</Note>
