Analytics & Usage Reports

Track AI, SMS, phone, voice, and member-level usage across your workspace for billing, budgeting, and cost analysis.

Intermediate
13 min read

Analytics & Usage Reports

Usage reports let organization owners and admins see where their workspace spends time, money, and messages. You can pull AI token consumption, SMS volume, phone minutes, voice (speech-to-text and text-to-speech) usage, and per-member totals, scoped to any date range you pick.

Reports are available in two ways: through the live Detailed Reports tab in Settings → Billing (/w/{wid}/settings/billing), and via the REST API for scripted exports, BI tools, or cost-allocation pipelines.

Who Can Access Reports

Usage reports return financial and operational data, so access is gated by scope:

ReportRequired scope
AI usage (/reports/ai-usage)analytics:read
SMS usage (/reports/sms-usage)analytics:read
Phone usage (/reports/phone-usage)analytics:read
Voice usage (/reports/voice-usage)analytics:read
Member usage — your ownmembers:read
Member usage — anyone else'sanalytics:read

The analytics:read scope is what the product calls "View analytics and reports." It's included in the default workspace manager and admin roles, and it's grantable to any custom role. See Roles & Permissions for how to assign scopes to a role.

Members can always see their own member-usage report. Only members with analytics:read can look at someone else's.

Getting an API Key

Reports are served by https://api.gravityrail.com. To call the endpoints you need a scoped API key:

  1. Go to AppsAPI Keys
  2. Click Create API Key
  3. Give it a clear name (e.g., "Monthly Billing Export")
  4. Pick an expiration (1–365 days)
  5. Grant the analytics:read scope — and members:read if you want to pull other members' usage
  6. Click Create and copy the key immediately (it won't be shown again)

Every request below uses the header Authorization: Bearer <YOUR_API_KEY>. See Apps & API Keys for more detail.

You'll also need your workspace UUID. It's the long identifier in your workspace URL (e.g., app.gravityrail.com/w/<workspace-uuid>/chats).

The AI Usage Report

The AI usage report summarizes everything your assistants generated: every chat message, every chat summary, every realtime voice turn. Use it to see which models are driving spend and which providers you lean on most.

Request

bash
Query parameterDefaultNotes
start_date30 days agoYYYY-MM-DD
end_datetodayYYYY-MM-DD

What the response contains

FieldWhat it means
total_messagesEvery message recorded in the workspace for the period — human and assistant, across all channels
total_tokensSum of prompt + completion tokens used by your assistants
total_cached_tokensPortion of input tokens served from the provider's prompt cache. Higher is cheaper
total_audio_input_tokens / total_audio_output_tokensRealtime voice audio tokens, tracked separately from text
total_creditsThe Gravity Rail unit of AI spend for the period (see Understanding Credits and Costs)
by_providerTotals broken out by provider (OpenAI, Anthropic, Google, AWS)
by_typeTotals split between chat and realtime models
top_modelsThe 10 models with the highest credit spend

What to look for

  • Providers drifting in the wrong direction. If one provider is creeping toward 80% of spend and you expected it to be 30%, a workflow is probably routing to the wrong model.
  • A model in top_models that surprises you. A development-grade model appearing in the top ten usually means a test workflow is running against real traffic.
  • Low total_cached_tokens vs. total_tokens. Prompt caching cuts cost substantially. A low ratio often means system prompts are being regenerated on every turn — worth investigating.

The SMS Usage Report

Every text your workspace sends or receives is tracked. The SMS report gives you a day-by-day, phone-number-by-phone-number picture of what went out and came in.

Request

bash
Query parameterDefaultNotes
start_dateStart of current UTC monthYYYY-MM-DD
end_dateEnd of current UTC monthYYYY-MM-DD

What the response contains

FieldWhat it means
totalMessagesAll SMS in the period
totalInbound / totalOutboundDirection split
totalCharactersSum of characters sent + received
totalSegmentsTotal carrier-billable segments (160 GSM chars / 70 Unicode chars per segment)
totalInboundSegments / totalOutboundSegmentsSegments by direction — useful when only outbound is metered
rows[]One row per date + phone number combination, each with its own inbound/outbound counts

What to look for

  • Segments, not characters. Carriers bill per segment, and a single long or emoji-laden message can be several segments. Use totalSegments for cost estimates.
  • Spikes on a single phone number. Drill into rows to see if one number is carrying the whole workspace — that's often a routing issue or a runaway campaign.
  • Inbound volume that dwarfs outbound. Healthy automated workflows usually send more than they receive. The reverse can point to members stuck in an unresolved loop.

The Phone Usage Report

The phone report covers voice calls in and out of your workspace numbers — the ones humans or AI answered. It only counts calls that reached a finished state with real start and end timestamps; missed and in-progress calls aren't included.

Request

bash
Query parameterDefaultNotes
start_dateStart of current UTC monthYYYY-MM-DD
end_dateEnd of current UTC monthYYYY-MM-DD

What the response contains

FieldWhat it means
totalCallsAll finished calls in the period
totalInbound / totalOutboundDirection split
totalDurationSecondsCombined talk time — divide by 60 for minutes
rows[]One row per date + phone number combination with inbound/outbound counts and duration

What to look for

  • Average call duration by number. Divide the row's totalDurationSeconds by (inbound + outbound) per day. A big jump usually means a workflow isn't hanging up when it should.
  • Outbound volume on a number meant for inbound. It's easy for a campaign to target the wrong line. The phone report surfaces that quickly.
  • Days with unusual volume. The daily breakdown makes it obvious when a single day drove a monthly spike.

The Voice Usage Report

Voice calls use two AI services under the hood: speech-to-text (STT) to transcribe what the caller says, and text-to-speech (TTS) to generate the assistant's reply. Voice usage is billed via credits at the org level, so this report shows usage volume only — durations, characters, and message counts.

Request

bash
Query parameterDefaultNotes
start_dateStart of current UTC monthYYYY-MM-DD
end_dateEnd of current UTC monthYYYY-MM-DD

What the response contains

FieldWhat it means
totalSttDurationSecondsTotal seconds of audio transcribed across all STT providers
totalSttMessagesNumber of STT calls (one per transcribed message)
totalTtsCharactersTotal characters converted to speech
totalTtsMessagesNumber of TTS calls
sttByProvider[] / ttsByProvider[]Totals broken out by provider and voice model
sttRows[] / ttsRows[]Daily breakdowns per provider + model

What to look for

  • Which voice provider is dominating. If you set up a premium voice for one agent and a cheaper one for everything else, the provider breakdown tells you whether the split is working.
  • TTS character growth. Long assistant replies burn through TTS faster than brief ones — this is often the single biggest voice-cost lever.
  • Models you don't recognize. A fallback model showing up unexpectedly usually means the primary model failed to load somewhere.

Member-Level Usage

The member usage report covers a single member's activity: chats they own, messages they sent, and AI usage incurred on their behalf. Org admins use it to allocate cost, and members can use it to check their own consumption.

Request

bash
Query parameterDefaultNotes
start_dateStart of current UTC monthYYYY-MM-DD
end_datetoday (UTC)YYYY-MM-DD

What the response contains

FieldWhat it means
memberIdThe member you queried
totalChatsChats created by this member in the period
totalMessagesMessages sent by this member (any role)
totalCreditsTotal tokens consumed across the member's chats and their chat summaries

Find member IDs from the People page or by listing members via GET /api/v2/w/{workspace_uuid}/members.

What to look for

  • Cost per seat, not just total cost. Comparing totalCredits across members normalizes spend by user, which is what billing and capacity conversations usually need.
  • Members with high message counts but low credits. That's a sign they're having short conversations — usually good. The reverse (few messages, many credits) often points to one long, expensive chat.
  • Discrepancies against the workspace-level AI report. Member usage attributes only what's anchored to a member's chats. System or agent-only work (e.g., scheduled routines) appears in the workspace total but not in any one member's report. That's by design.

Understanding Credits and Costs

Gravity Rail measures AI spend in two related ways:

  • Tokens are the raw unit your AI provider counts — roughly one token per four characters of English text.
  • Credits are Gravity Rail's normalized unit of AI spend. Each model has a multiplier that converts its tokens into credits, so a premium model and a lightweight model consume different numbers of credits per token. Credits are what you'll see on your bill and what org-level quotas are enforced against.

Both are pre-calculated at the moment usage is recorded. That means:

  • Historical reports are locked to the prices that applied at the time. If a provider lowers their prices next month, old reports won't retroactively get cheaper.
  • You don't need to re-derive credits from tokens yourself. The number in the report is the authoritative one; credit multipliers can change over time and per-model, so recomputing downstream will drift.

For SMS and phone, the report gives you the raw usage primitives — messages, characters, segments, duration. Your carrier pricing converts those to dollars. Voice STT/TTS is billed via org-level credits, and the credit totals appear on your org billing, not in the voice-usage payload.

Date Ranges and the UTC Caveat

Every report accepts optional start_date and end_date parameters as YYYY-MM-DD. Both are inclusive2026-04-01 to 2026-04-30 covers the whole of April.

All daily breakdowns are bucketed in UTC. That is important:

  • A call that starts at 10:00 PM Pacific on April 30 ends up on May 1 in the report, because that's 5:00 AM UTC May 1.
  • If you're in the eastern U.S., daily totals roll over at 8:00 PM local (standard time) or 7:00 PM (daylight time) — not midnight.
  • Month totals align to UTC month boundaries. If your billing cycle ends on the last calendar day in your local time zone, ask for an extra day on either side and filter the rows yourself.

Defaults follow the same rule: the SMS, phone, and voice reports default to the start-of-month and end-of-month in UTC, and member usage defaults to "start of the current UTC month." If month alignment matters, pass the dates explicitly.

Tips

  • Export once a month, reconcile once a quarter. Pulling the AI, SMS, phone, and voice reports on the first of each month and parking them in a spreadsheet is the simplest path to trend analysis.
  • Rotate API keys that you use for exports. A 90-day expiration on the key you feed into a BI tool is a healthy default — see Apps & API Keys.
  • Scope sub-minute conversations carefully. Phone reports round to the second, but very short calls (a dial and immediate hangup) are included and can inflate call counts. Filter the rows if you want only "real" conversations.
  • Use the smallest date range that answers your question. A 90-day AI report aggregates millions of rows in large workspaces. Narrow the range when you're iterating.
  • Watch the realtime/chat split. In by_type, realtime models are usually much more expensive per minute than chat models. If realtime credits climb without a corresponding increase in phone calls, that's worth a look.

Troubleshooting

"403 Forbidden" when requesting a usage report

Your API key doesn't include analytics:read. Create a new key with that scope, or update the role on the member whose API key you're using. Member-level usage for your own member ID only requires members:read; any other member requires analytics:read.

Numbers don't match my provider invoice

A few common causes:

  • Time zone. The report is UTC; your invoice is almost certainly in a local time zone.
  • Pending calls or messages. In-progress or not-yet-finished calls don't appear in the phone report.
  • Cached tokens. AI providers typically discount cached prompt tokens. total_cached_tokens shows how much of your input was cached — this is usually the source of the discrepancy between raw token counts and billed amounts.

A member's usage looks lower than expected

Member usage attributes activity to the member who owns the chat. Agent-only work, scheduled routines, and system-initiated chats aren't attributed to any member and won't appear in their report. Cross-check against the workspace-level AI usage report for the full picture.

The report is slow

Large date ranges across large workspaces aggregate millions of rows. Narrow the date range, or split a yearly pull into monthly requests and combine the results client-side.