You need an organization API key whose scope is read or admin, plus the project id. An ingest-only key cannot call these routes. A key limited to one project works only for that project. Create the key under API Keys in the Lemma dashboard.
Find events and fields in the catalog
Every query reads one event, such astrace.processed or tool.called. The catalog lists each event with the fields you can filter and group by (dimensions), the fields you can aggregate (measures, each with its allowed aggs), and any cost_measures. It also lists filter_ops, buckets, and limits.
describe_project_analytics with project_id. A field that isn’t in the catalog can’t be queried.
Send a query
POST the query body to /projects/{project_id}/analytics/query:
query_project_analytics with project_id plus the same body. MCP uses camelCase for three keys: endExclusive, groupBy, and orderBy. Field names such as agent_name stay snake_case in both.
Build the query body
A body names an event infrom, a window in start and end_exclusive, and at least one measure. The window is UTC, on whole seconds, with the end exclusive. Optional keys narrow or shape the result:
- Measures: what to compute, each with an alias in
as, and an optional per-measurefilter - Filters: conditions every counted row must match
- Groups and order: split by a time bucket or a field, then sort
- Join: add measures from one other event
Read the response
A response hasrows, one object per group keyed by your aliases, plus truncated and the queried window. When truncated is true, further rows exist, so narrow the filters or raise limit. REST and MCP return the same snake_case shape. See Query response.
An invalid query returns HTTP 400 with the reason. Query errors lists each message and its cause.
Examples
Each example below is a complete body. Save it asquery.json and send it with the request in Send a query.
Daily volume and latency for one agent
Count one agent’s traces per day, with the 95th percentile of root duration. Ontrace.processed, root duration is root_duration_ms:
p95_ms is in milliseconds.
Tools that fail most
Rank tools by failed calls. Ontool.called, error is 1 when the tool span failed and 0 otherwise, so its sum is the failure count:
failures by calls for the failure rate. This row is 4.5%:
Estimated cost by model
Estimate generation cost per model.generation_cost needs a model group with the alias model:
estimated_cost_usd, not under the cost alias:
priced: false means Lemma has no list price for that model, and estimated_cost_usd is null.
Runs with errors by agent
Count each agent’s traces, and the traces where any span failed. The second measure’sfilter limits it to traces with error_count above zero:
Traces and tool use per agent
Join tool calls to traces onagent_name. uniqExact on tool counts the distinct tools each agent called:
Cost estimates
trace_cost and generation_cost are estimates from recorded token counts and public list prices, not an invoice. Cost fields lists what each adds to a row, including cost_lower_bound when the estimate can be low.
Preset views
GET /projects/{project_id}/analytics returns one dashboard panel. Pass one view. MCP has one tool for each view. View names, MCP tools, parameters, and responses are on Analytics query API.
Related pages
Analytics query API
Every event, field, rule, error, and preset view.
Analytics
Dashboard charts for volume, latency, errors, tools, models, and cost.
Analytics catalog
Events, fields, filters, and limits for a project query.
Query project analytics
The REST operation for one aggregate.
Analytics telemetry
SDK fields the aggregates are computed from.