Analytics query cookbook
Copy-paste recipes for common questions. Each is the query value you send to
POST /query. See the Schema reference for every column.
Reminder: monetary columns are cents (divide by 100;
fact_cost.cost_amount is fractional cents), and UInt64/Int64 results
come back as JSON strings.
Prerequisites
- A Paid API key with access to your organization’s Analytics API.
- Signals, costs, delivered value, invoices, or credit activity already present for the tables you want to query.
- Familiarity with the table names and joins in the Schema reference.
Usage & signals
Total signals in the last 30 days
Signal volume by type
Daily signal time-series
Signals by customer (resolving names)
Querying signal metadata
Signals carry a free-form JSON data payload. Access a field with
data.<path> and cast it to a type. First discover available keys with
GET /signals/metadata, then filter or group on them.
Casting a missing key with ::String yields an empty string (''), not
NULL, so a '' bucket in a grouped result represents signals that don’t
carry that key.
Group by a string metadata field
Filter on a metadata field
Aggregate a numeric metadata field
AI cost
cost_amount is exact fractional cents (a typical AI call costs a fraction of
a cent), so SUM(cost_amount) / 100 gives exact dollars and matches the Cost
Explorer in the Paid UI.
Total spend (dollars) by vendor
Spend by model with token usage
Daily cost trend
Cost by customer
Cost per signal (joining usage and cost)
Signals and costs share a trace_id, so you can attribute AI cost to the
signal that incurred it.
Revenue
Monthly revenue (posted invoices)
Revenue by customer
Revenue by product (invoice lines → order lines → products)
Fixed-fee vs usage revenue split (posted invoices)
charge_type is usage for metered lines and oneTime/recurring/seatBased
for fixed charges. It is empty on manual lines (no linked pricing) and on lines
predating charge-type attribution. Bucket those as unknown rather than folding
them into fixed, or they will inflate the fixed-fee share.
A non-trivial unknown total means manual/unattributed lines carry real revenue.
inspect them before treating the fixed-vs-usage split as complete. For the full
breakdown, group by il.charge_type directly
(oneTime / recurring / seatBased / usage, plus empty for unattributed).
Outstanding / overdue invoices
Payments / cash flow
Billed usage
Which signals drive billed revenue
Overage (usage above the included allowance)
Credits
Net credit flow by currency
Top credit-spending signals
Credit consumption by user within a customer
If your signals include external_user_id in the data payload (see
First signals),
you can break down credit spend per user:
Delivered value
delivered_value_cents is denominated in each row’s
delivered_value_currency, which is not always USD — organizations using
value models can deliver value in EUR, GBP, etc. Always group by (or filter
on) delivered_value_currency; summing cents across currencies produces
meaningless totals. Cents are exact and may carry fractions, so round after
aggregating.
Value delivered by type
Value vs. cost (ROI) by customer
Paginating large result sets
Results are capped at 10,000 rows. For larger extracts, page with a WHERE
filter on an ordered column (keyset pagination) rather than a large OFFSET: