Skip to main content

Usage tracking API

The usage tracking system records per-event token consumption and tool execution metrics. You can query aggregated data by agent, model, or time period.
The usage tracker records events to a PostgreSQL database whenever an AI completion or tool call is made. The endpoints below are read-only query APIs for retrieving aggregated usage data. When no real usage data exists yet, the cost dashboard returns sample data with a isMockData: true flag.

Test usage logging (deprecated)

This endpoint was removed in the March 2026 security audit and is no longer available. Requests to this path return 404. Use the cost dashboard endpoint to verify that usage tracking is working.
POST /api/test-usage
A debug endpoint that fires a single test event through the usage logging pipeline.

Cost dashboard

GET /api/dashboard/cost
Returns aggregated cost, token, and call data for the cost dashboard. Breaks down spending by agent, model, and day. Requires session authentication. When no usage data is available, the endpoint returns realistic sample data with isMockData set to true and a message field explaining that usage tracking is not yet configured.

Query parameters

ParameterTypeDefaultDescription
periodstring7dTime window for the aggregation. Accepted values: 7d (last 7 days), 30d (last 30 days), mtd (month to date).

Response

{
  "period": "7d",
  "summary": {
    "totalCost": 13.68,
    "totalTokens": 4560000,
    "totalCalls": 1946,
    "avgCostPerCall": 0.007
  },
  "agents": [
    {
      "name": "Atlas",
      "tokens": 2840000,
      "cost": 8.52,
      "calls": 1247,
      "avgCostPerCall": 0.0068,
      "model": "claude-3-7-sonnet"
    }
  ],
  "daily": [
    {
      "date": "Mar 17",
      "cost": 1.42,
      "tokens": 380000
    }
  ],
  "modelBreakdown": [
    {
      "model": "claude-3-7-sonnet",
      "percent": 68,
      "cost": 9.30
    }
  ],
  "isMockData": false
}

Response fields

FieldTypeDescription
periodstringThe requested period echoed back (7d, 30d, or mtd)
summary.totalCostnumberTotal cost in USD for the period
summary.totalTokensnumberTotal tokens (input + output) consumed
summary.totalCallsnumberTotal API calls made
summary.avgCostPerCallnumberBlended average cost per call in USD
agentsarrayPer-agent cost breakdown, sorted by cost descending
agents[].namestringAgent name or identifier
agents[].tokensnumberTotal tokens consumed by the agent
agents[].costnumberTotal cost in USD attributed to the agent
agents[].callsnumberNumber of API calls made by the agent
agents[].avgCostPerCallnumberAverage cost per call for the agent
agents[].modelstringPrimary model used by the agent
dailyarrayDaily cost and token totals
daily[].datestringFormatted date label (e.g. "Mar 17")
daily[].costnumberCost in USD for that day
daily[].tokensnumberTotal tokens consumed that day
modelBreakdownarrayCost breakdown by model, sorted by cost descending
modelBreakdown[].modelstringModel identifier
modelBreakdown[].percentnumberPercentage of total cost attributed to this model
modelBreakdown[].costnumberCost in USD for this model
isMockDatabooleantrue when the response contains sample data because no real usage data is available
messagestring | undefinedPresent only when isMockData is true. Explains that sample data is being returned.

Errors

CodeDescription
500Failed to fetch cost data

The remaining endpoints on this page are planned for a future release. They are not yet available. Usage events are recorded internally but these query APIs have not been deployed. This section documents the intended specification for reference.
All query endpoints below require bearer token authentication and are served by the backend API.

Usage summary

GET /api/usage/summary
Returns daily aggregated token usage and cost data across all agents and models.

Query parameters

ParameterTypeDefaultDescription
daysinteger30Number of days of history to return

Response

[
  {
    "date": "2026-03-22",
    "agent_id": "agent_abc",
    "model": "openrouter/anthropic/claude-sonnet-4",
    "provider": "openrouter",
    "input_tokens": 15200,
    "output_tokens": 3400,
    "total_tokens": 18600,
    "cost_usd": 0.042,
    "turn_count": 12
  }
]

Response fields

FieldTypeDescription
datestringDate in YYYY-MM-DD format
agent_idstring | nullAgent that generated the usage, or null for unattributed events
modelstringModel identifier
providerstringAI provider name
input_tokensnumberTotal input tokens for the day
output_tokensnumberTotal output tokens for the day
total_tokensnumberSum of all token types (input, output, cache read, cache write)
cost_usdnumberEstimated cost in USD
turn_countnumberNumber of individual completion calls

Usage by agent

GET /api/usage/by-agent/:agentId
Returns token usage grouped by model for a specific agent.

Path parameters

ParameterTypeDescription
agentIdstringID of the agent to query

Query parameters

ParameterTypeDefaultDescription
daysinteger30Number of days of history to include

Response

[
  {
    "model": "openrouter/anthropic/claude-sonnet-4",
    "provider": "openrouter",
    "input_tokens": 45000,
    "output_tokens": 12000,
    "total_tokens": 57000,
    "cost_usd": 0.13,
    "events": 48
  }
]

Response fields

FieldTypeDescription
modelstringModel identifier
providerstringAI provider name
input_tokensnumberTotal input tokens
output_tokensnumberTotal output tokens
total_tokensnumberTotal tokens across all types
cost_usdnumberEstimated cost in USD
eventsnumberNumber of usage events

Usage by model

GET /api/usage/by-model
Returns token usage aggregated by model across all agents.

Query parameters

ParameterTypeDefaultDescription
daysinteger30Number of days of history to include

Response

[
  {
    "model": "openrouter/anthropic/claude-sonnet-4",
    "provider": "openrouter",
    "input_tokens": 120000,
    "output_tokens": 35000,
    "total_tokens": 155000,
    "cost_usd": 0.35,
    "turns": 200
  }
]

Response fields

FieldTypeDescription
modelstringModel identifier
providerstringAI provider name
input_tokensnumberTotal input tokens
output_tokensnumberTotal output tokens
total_tokensnumberTotal tokens across all types
cost_usdnumberEstimated cost in USD
turnsnumberTotal completion turns

Daily totals

GET /api/usage/daily
Returns total token usage and cost per day.

Query parameters

ParameterTypeDefaultDescription
daysinteger7Number of days of history to return

Response

[
  {
    "date": "2026-03-22",
    "total_tokens": 85000,
    "cost_usd": 0.19,
    "turns": 72
  },
  {
    "date": "2026-03-21",
    "total_tokens": 62000,
    "cost_usd": 0.14,
    "turns": 55
  }
]

Response fields

FieldTypeDescription
datestringDate in YYYY-MM-DD format
total_tokensnumberTotal tokens used that day
cost_usdnumberEstimated cost in USD
turnsnumberTotal completion turns

Tool stats

GET /api/usage/tools
Returns aggregated tool execution statistics, optionally filtered by agent.

Query parameters

ParameterTypeDefaultDescription
agentIdstringFilter results to a specific agent. Omit for all agents.
daysinteger7Number of days of history to include

Response

[
  {
    "tool_name": "web_search",
    "calls": 150,
    "successes": 142,
    "avg_ms": 1230.5
  },
  {
    "tool_name": "code_edit",
    "calls": 85,
    "successes": 83,
    "avg_ms": 450.2
  }
]

Response fields

FieldTypeDescription
tool_namestringName of the tool
callsnumberTotal number of invocations
successesnumberNumber of successful invocations
avg_msnumberAverage execution duration in milliseconds

Usage event schema

Each usage event is stored as a row in the usage_logs table (Prisma model name: UsageLog). Events are recorded automatically whenever an AI completion is made (for example, from the demo chat endpoint or agent chat). Cost is calculated at write time using per-model pricing rates.
The usage_logs table is created via a dedicated SQL migration (20260323000000_add_usage_logs) rather than through Prisma’s schema push. This ensures the table is created reliably across deployments without requiring Prisma to manage the migration state.

Server-side logging

Every usage event emits a structured log line to the server console when it is recorded. This makes it possible to verify that the usage tracking pipeline is working without querying the database. Success log format:
[UsageLogger] Logging: <agentId> | <model> | <inputTokens>+<outputTokens> tokens | $<cost>
For example:
[UsageLogger] Logging: demo-chat | gpt-4o | 450+120 tokens | $0.004050
If the database write fails, an error is logged instead:
[UsageLogger] Failed to log usage: <error message>
Because usage recording is fire-and-forget (it never blocks the API response), these log lines are the primary way to diagnose write failures. Monitor your server logs for [UsageLogger] Failed to log usage entries if usage data appears to be missing from the cost dashboard.

Cost dashboard logging

The cost dashboard endpoint emits its own diagnostic log lines prefixed with [Cost API]. These help you verify that the aggregation query is running and returning data. Query result log:
[Cost API] Found <count> usage logs
For example:
[Cost API] Found 42 usage logs
If the Prisma query fails, the endpoint logs the error and falls back to sample data:
[Cost API] Prisma error: <error message>
If the entire handler fails, a general error is logged and a 500 response is returned:
[Cost API] Error: <error message>
FieldTypeDescription
idintegerAuto-incrementing primary key
user_idvarchar(255)User who triggered the event
agent_idvarchar(255)Agent that triggered the completion
modelvarchar(100)Model identifier (for example anthropic/claude-sonnet-4.5)
input_tokensintegerNumber of input (prompt) tokens. Defaults to 0.
output_tokensintegerNumber of output (completion) tokens. Defaults to 0.
cost_usddecimal(10,6)Computed cost in USD (six decimal places). Defaults to 0.
endpointvarchar(255) | nullAPI route that generated the event (for example /api/demo/chat)
latency_msinteger | nullResponse latency in milliseconds
successbooleanWhether the completion succeeded. Defaults to true.
error_messagetext | nullError description when success is false
created_attimestampTimestamp when the event was recorded. Defaults to NOW().
When accessing the table through the Prisma ORM, use the camelCase field names (userId, agentId, inputTokens, etc.). When writing raw SQL queries, use the snake_case column names shown above (user_id, agent_id, input_tokens, etc.).
The table is indexed on user_id, agent_id, created_at, and the composite pairs (user_id, created_at) and (agent_id, created_at) for efficient time-range queries.
The usage event schema was updated in the March 2026 release. The previous fields session_id, session_key, cache_read_tokens, cache_write_tokens, and total_tokens are no longer recorded. Use input_tokens + output_tokens to calculate total tokens.

Tool event schema

Each tool event records:
FieldTypeDescription
session_idstring | nullSession that triggered the tool call
agent_idstring | nullAgent that invoked the tool
tool_namestringName of the tool
successbooleanWhether the tool call succeeded
duration_msnumber | nullExecution time in milliseconds

Errors

All usage tracking endpoints return the following error codes:
CodeDescription
401Unauthorized — missing or invalid bearer token
500Database query failed