HTTP API
Everything the dashboard shows is a plain JSON endpoint you can build on. When auth is locked, the /api/* read endpoints require a session cookie; /api/track also accepts a project gateway key.
Proxy routes
| Route | Notes |
|---|---|
/p/<project>/<provider>/… | Proxy a call, grouped under a project |
/k/<key>/<provider>/… | Proxy under auth - the key sets the project |
/<provider>/… | Proxy with x-aicc-project header (or “default”) |
Data endpoints
| Method + path | Returns |
|---|---|
GET /health | { ok, name, version, uptimeMs } |
GET /api/meta | version, branding, currency, providers, record count |
GET /api/stats?range=7d&project=x | totals, timeseries, by-project / by-model / by-provider |
GET /api/requests?limit=100&errorsOnly=1&q=gpt | recent requests (newest first) |
GET /api/projects | known projects with totals |
GET /api/fx | current display currency + exchange rates |
GET /api/events | Server-Sent Events - live request feed |
GET /api/traces?range=7d | sessions grouped by trace id (newest first) |
GET /api/trace?id=… | the ordered call timeline for one trace |
GET /api/prompts?range=7d | per prompt+version cost, latency and error rate |
GET /api/models?range=7d | model comparison (effective $/1M tok, p50/p95, error rate) |
GET /api/anomalies?range=30d | rule-based cost-spike / error-burst flags |
GET /api/alerts | active alerts + budgets (spend vs limit) + thresholds |
POST /api/track | ingest external usage (see below) |
POST /api/admin/budget | admin: set a project budget { project, monthlyUsd, alertAtPct } |
DELETE /api/records?simulated=1 | remove demo records (admin; drop the query to wipe all) |
Requests may carry x-aicc-trace, x-aicc-prompt and x-aicc-prompt-version headers (or the same fields in a /api/track body) to power the Traces and Prompts views. See Traces, prompts & budgets.
range accepts 1h · 24h · 7d · 30d · 90d · all, or explicit from/to epoch-ms.
POST /api/track
Report usage the proxy can't see. Cost is computed for you if you omit costUsd. Send one object or an array (up to 1000 records per call).
curl -X POST http://localhost:4321/api/track \
-H "Content-Type: application/json" \
-d '{
"project": "nightly-job",
"provider": "openai",
"model": "gpt-4o",
"tokensIn": 52000,
"tokensOut": 9000,
"latencyMs": 820
}'{ "saved": 1 }Not just LLMs: track any AI spend
This is the first-class path for costs that never pass through the proxy - speech-to-text, TTS, telephony minutes, image generation, embeddings run elsewhere, batch jobs. Three fields make it composable:
costUsd- set it explicitly for anything priced per minute/character/call instead of per token; the pricing engine is skipped and your number is recorded as-is.trace- use the same trace id as the LLM calls around it and the whole pipeline (STT → LLM → TTS) shows up as one session on the Traces view, with a true total cost.ts- epoch-ms timestamp for backfills: import yesterday's batch or a provider invoice and it lands on the right day in every chart.
curl -X POST http://localhost:4321/api/track \
-H "Content-Type: application/json" \
-d '[
{ "project": "voice-agent", "provider": "stt", "model": "streaming-stt",
"trace": "call-8123", "costUsd": 0.0062, "latencyMs": 240 },
{ "project": "voice-agent", "provider": "tts", "model": "neural-tts",
"trace": "call-8123", "costUsd": 0.0031 },
{ "project": "voice-agent", "provider": "telephony", "model": "sip-minutes",
"trace": "call-8123", "costUsd": 0.0140, "ts": 1783605600000 }
]'Example: pull today's spend
curl -s "http://localhost:4321/api/stats?range=24h" \
| python3 -c 'import json,sys; print("$%.2f" % json.load(sys.stdin)["totals"]["costUsd"])'