Skip to main content
The billing endpoints answer “where do we stand?” without you stitching a picture together from a dozen calls. Start with the summary. Reach for the lists only when you need the detail behind a number. Every billing read covers your own agency: the one your API key belongs to. There is no parameter that selects another.

Where you stand

GET /api/billing/summary returns one object with these sections. Each section loads on its own. When one cannot be loaded it comes back null and its name appears in unavailable. So a null section named in unavailable means “unknown right now”, and any other null means “none”. attention lists what needs a person, most urgent first. Each item has a code, a severity (ACTION_REQUIRED, WARNING or INFO) and a message you can show as it is. An agency exempt from payment is never told its wallet is low.

The transaction history

GET /api/billing/transactions is one paged list of everything that moved your agency wallet in a window, newest first. walletEffect is what the row did to your wallet. cashFlow is whether money changed hands. For SUB_ACCOUNT_TOP_UP, amountUSD is what the sub-account paid you. CALL_USAGE counts only calls your wallet paid for: calls from sub-accounts that do not rebill, calls you covered when a rebilled sub-account had no card, and the part of a call that ran past a sub-account’s minutes. A call a sub-account paid for from its own minutes is not a second charge to you, so it is not on this list. It is in the usage figures below. Filter with type and locationId. Filtering by sub-account leaves out agency-level rows such as your own purchases.

Usage and cost

GET /api/billing/usage totals a window and breaks it down by sub_account (the default) or by day. callCostUSD and billedToClientsUSD describe the calls, so they lag the money: a sub-account that bought minutes it has not used yet has paid you for them already. Phone numbers and co-author usage belong to your agency, so they appear in totals and in each day, never under a sub-account.

Sub-account wallets

GET /api/billing/sub-accounts lists every connected sub-account. A disconnected one is not listed.
  • rebilling: whether the sub-account pays for its own calls from its own wallet, and the clientRatePerMinute you charge it.
  • wallet: balanceMinutes (bonus minutes included, expired batches not), balanceUSD, debtMinutes, and whether the sub-account can see its wallet (visibility, ENABLED or DISABLED).
  • autoRecharge: set in dollars. thresholdUSD is the dollar balance it tops up below, and rechargeAmountUSD is what each top-up charges.
  • creditGuard: whether the sub-account stops its own calls when its wallet is empty.
  • pendingCredits: payments the sub-account has made that are waiting for credit in your wallet.
The wallet status is ACTIVE, LOW_BALANCE, IN_DEBT or DEPLETED. A sub-account that does not rebill is funded by your wallet, so an empty balance there is normal. The summary only flags rebilled ones. GET /api/billing/sub-accounts/{locationId} adds the creditBatches behind the balance, oldest first, which is the order they are drawn down.

Invoices and receipts

GET /api/billing/documents lists proof of payment.
  • scope=platform (the default): what your agency paid the platform. An INVOICE for your subscription, a RECEIPT for each wallet top-up.
  • scope=sub_accounts: what your sub-accounts paid you. Always a RECEIPT.
Narrow with type (ALL, INVOICE or RECEIPT). The platform list is built from two sources and capped. When truncated is true, it is not complete history.

Changing billing

The same module changes billing. Two scopes split it by what a call does to money:
  • billing:write changes settings. Nothing is charged when the call returns, though switching auto-recharge on permits charges later.
  • billing:charge charges a card when the call returns. billing:write does not include it, every such operation needs an Idempotency-Key, and none of them is available to an assistant over MCP.
For your agency: For a sub-account, every change needs your plan to include rebilling and Stripe Connect to be connected, even a change that turns something off: The walkthrough is Set up rebilling for a sub-account.

Windows

dateFromUTC and dateToUTC select whole UTC days. A timestamp selects the day it falls on. Leave both out and the history and usage endpoints read the last 30 days. A window can cover at most 366 days. Documents are not windowed unless you ask. See Conventions.

Boundaries

  • Adding cards, creating Stripe customers and connecting Stripe stay in the dashboard. The API never takes card details.
  • Anything that charges a card needs the billing:charge scope and an Idempotency-Key, and is not available over MCP.
  • Only an agency admin’s credential can change billing. Reads also admit a staff credential carrying an agency of its own. A sub-account user gets 403 either way, because every figure here is agency-wide.
  • A key needs the billing:read scope to read. billing:write covers it. billing:charge covers neither.
  • A sub-account belongs to the agency that owns it. One that is only shared with you is not in your billing.
  • A locationId that is not one of your connected sub-accounts returns 404, whether it does not exist or belongs to someone else.

In the API