Skip to main content
Operator-facing surface. This guide walks the Billing → Records dashboard page (/billing/records). For the API the page reads from — GET /usage/cdr and GET /usage/cdr/export.csv — see CDR usage export for billing reconciliation. The dashboard and the API expose the same usage records; the page is the faster path for an operator who wants to filter, eyeball, and download CSV without leaving the console.

Billing → Records: the usage record export console

Open Billing → Records (/billing/records) and you land on the single page built for one job: turn a month of calls and messages into two CSV files finance can reconcile line-for-line against the wallet ledger. The page pairs a live usage feed with two export panels — one per-call (voice CDR), one per-message — over one shared filter window, so the records you see in the table are the records you download. This is the dashboard walkthrough. For the request/Response contract, the keyset-cursor drain loop, the CSV column order, and the per-bucket reconciliation script, read the API-focused guide. This guide assumes you are an operator in the console, not at a terminal.

1. What the page is

/billing/records is the shared-window CSV export hub. It unifies the two billing-reconciliation surfaces — voice CDR (one row per call) and messaging usage (one row per message) — that previously lived as separate exports, and sits them over one filter strip so both exports honor the same window, the same channel scope, and the same status slice. Set the filters once; both panels and the live table read the same coverage. The page exists so a finance operator can answer “what did we spend this month, broken down to the record” in one click rather than one script. The role gate matches the API: owner, admin, or billing. If you can open the page you can export its data; if you cannot, the API is equally gated.
Billing → Records page: the shared filter strip, the live usage table, and the two export cards.

2. The shared-window filter strip

Every control in the filter card at the top of the page applies to the live table and both export panels at once. Change one filter and all three surfaces re-scope to the same window — there is no per-panel filter drift. The controls, left to right:
  • Window (7d / 30d / 90d) — a preset “last N days” range picker in the page header. The default is 30d. The window resolves to an inclusive from and an exclusive to (now) in UTC, so the live table and the CSV export see the same rows for the same window.
  • Direction — All (both legs), Inbound, or Outbound. Applies to both call and message records.
  • Channel — All channels, or one of SMS, MMS, WhatsApp, Voice, Email, RCS. Calls carry the synthetic Voice channel, so selecting it scopes the table to the call arm.
  • Record kinds — toggle chips for Calls and Messages. Leave both off for both record kinds; toggle one to drain a single kind (the server-side resolver drops the disabled arm rather than over-fetching).
  • Status — a free-form text field with suggestions (delivered, sent, queued, failed, undelivered, bounced, expired, answered, completed). One key spans both record kinds; an unrecognized token matches nothing but never errors the request.
  • Phone (CDR export only) — an E.164 phone number. This filter reaches only the voice CDR export card — the unified message-export schema has no phone bound, so the field would silently no-op there. The page labels it accordingly so a scoped export never silently drops to “all numbers.”
  • Pricing — All records (priced + unpriced) or Priced only. The default keeps rows whose price was never rated so the feed never looks like “no usage” when a rating hiccup left a NULL price. Switch to Priced only to restrict to billed rows.
A scope note under the filter card states which controls reach which surface: the phone filter is CDR-only, and every other filter applies to the table and both export cards.

3. Voice panel — call records (voice CDR)

The Call records (voice CDR) export card streams one row per call, priced with the settled per-minute rate the wallet was charged at call close. It drives the voice export endpoint with the shared window and the direction, status, and phone filters from the strip above. Pick the direction at the strip — All, Inbound, or Outbound — and the card exports that leg. Each row in the exported CSV carries:
  • Direction — inbound or outbound.
  • From — the calling party address.
  • To — the called party address.
  • Duration — the billed call duration.
  • Price — the per-call settled price the wallet was charged.
  • Currency — the currency the price is denominated in.
  • Country — the destination country the rate card billed the call against.
Click Export call records to download the CSV. The file is named usage-cdr-records-<timestamp>.csv. Up to 100,000 rows per pull; the card priced each row at the per-minute rate the wallet ledger saw at close — the export never re-rates.

4. Messaging panel — message records

The Message records (SMS / WhatsApp / …) export card streams one row per message across every channel in the account — SMS, MMS, WhatsApp, Email, RCS, and the rest — priced with the per-message rate the wallet was charged at send time. It drives the message export endpoint with the shared window and the channel and status filters from the strip. Each row in the exported CSV carries:
  • Direction — inbound or outbound.
  • From / To — the sender and recipient addresses.
  • Channel — the channel the message rode on (SMS, WhatsApp, Email, RCS, …).
  • Segments — the billable segment count the message was rated on (the unit the carrier bills — one long SMS may be two or three segments).
  • Price — the per-message settled price the wallet was charged.
  • Currency — the currency the price is denominated in.
  • Status — the delivery status at export time.
Click Export message records to download the CSV. The file is named usage-messages-records-<timestamp>.csv. Up to 10,000 rows per pull; channel-scope the export by setting a channel in the filter strip above before you export — the message-export schema has no phone bound, so the phone filter does not reach this card.

5. How the page reconciles

The live table above both export cards subscribes to the same usage feed the CDR API exposes — the records you see in the table are the records that land in the CSV. Each row carries its resolved price inline, so per-record reconciliation against the wallet ledger is exact, not an estimate. The table keyset-paginates (a server-validated (timestamp, id) cursor) with a Load more records affordance; a Load more click fetches the next page over the same window without resetting the filter. A Export CSV link in the table header drives the unified usage-CDR export — the same filter set in one pass — so the table and the export never disagree on which rows match. This is where the dashboard and the API divide: the dashboard is operator-friendly — filter, eyeball, download, repeat. For a finance-grade close that pages the whole month, drains a 50,000-row cap, and matches rows against an invoice line-for-line, the CDR export API is the path. The dashboard readings aggregate and round by design; the CSV the page downloads carries the same per-record prices the API returns.

6. Role gate

The page is gated to owner, admin, or billing — the same roles the CDR export API requires. The gate matches every sibling billing surface so a finance operator never hits a 403 halfway through a reconciliation sweep. If you can open /billing/records you can read and export the feed; the API is equally gated.
  • CDR usage export for billing reconciliation — the API-focused guide for GET /usage/cdr and GET /usage/cdr/export.csv: keyset-cursor pagination, the CSV column order, the rate limit and row cap, and the worked month-end reconciliation script. Read it when the dashboard’s 100,000-row voice cap or 10,000-row message cap is too small, or when a warehouse sync needs the JSON drain.
  • Revenue recognition: read deferred vs recognized schedules — the downstream cost-center walkthrough for turning the records this page exports into a recognized-vs-deferred schedule per contract.
  • Read the cost-intelligence dashboards — the Billable usage records panel on the cost-intelligence surface aggregates the same per-record feed this console exports into carrier-parity counters by SMS, MMS, and voice. Read it when the reconciliation question is “what does a carrier bill us for” rather than “which records sum to this invoice line.”