Claude API Usage Analytics Dashboard Setup Guide
If you're calling the Claude API in production, you eventually hit the same wall: you can see your Anthropic bill at the end of the month, but you have no real-time visibility into who's consuming tokens, which endpoint is driving costs, or whether a specific feature is about to blow your budget. Setting up a usage analytics dashboard means capturing per-request metadata (tokens, latency, model, cost, caller) and surfacing it somewhere queryable — either by building it yourself or using a layer that already tracks it for you.
This guide covers both paths: a DIY setup using logging and a time-series store, and a faster setup using a gateway that already exposes usage metadata per API call. By the end you'll know what fields to track, how to structure the pipeline, and what tradeoffs each approach has.
What a usage analytics dashboard actually needs to track
Before picking tools, define the data model. For Claude API usage, the fields that actually matter are:
- Input tokens and output tokens per request (these have different prices)
- Model name (Opus, Sonnet, Haiku all have different per-token costs)
- Timestamp for time-bucketed charts (daily/weekly/monthly)
- Caller identity — which user, team, or API key made the request
- Latency (time to first token and total completion time, if you care about performance)
- Stop reason (helpful for spotting truncated responses or errors)
- Request status (success, rate limited, error)
If you're only tracking token totals, you'll see cost but miss the "who" and "why." If you're only tracking by user but not by model, you'll miss that someone accidentally pointed a script at Opus instead of Haiku and tripled their spend.
Option 1: Build it yourself with Claude's response metadata
Every Claude API response includes a usage object with input_tokens and output_tokens. The setup pattern is:
- Wrap your Claude API calls in a logging middleware
- Extract
usagefrom each response and attach caller metadata - Write rows to a time-series-friendly store (Postgres with a timestamp index, or a dedicated store like ClickHouse/Timescale if volume is high)
- Build dashboard queries on top (Grafana, Metabase, or a custom admin page)
A minimal logging wrapper looks like this:
async function callClaudeAndLog(payload, userId) {
const start = Date.now();
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json"
},
body: JSON.stringify(payload)
});
const data = await res.json();
const latencyMs = Date.now() - start;
await db.insert("usage_events", {
user_id: userId,
model: payload.model,
input_tokens: data.usage?.input_tokens ?? 0,
output_tokens: data.usage?.output_tokens ?? 0,
stop_reason: data.stop_reason,
latency_ms: latencyMs,
created_at: new Date()
});
return data;
}
From there, a daily cost query is just:
SELECT
date_trunc('day', created_at) AS day,
model,
SUM(input_tokens) AS total_input,
SUM(output_tokens) AS total_output
FROM usage_events
GROUP BY 1, 2
ORDER BY 1 DESC;
This works fine for a single app with a handful of integrations. It gets harder once you have multiple teams, multiple services calling Claude, and you need per-team billing breakdowns, rate limit enforcement, and key rotation — at that point the "DIY logging table" turns into a small internal platform you now have to maintain.
Option 2: Use a layer that already tracks usage per key
If you don't want to build and maintain the logging/aggregation pipeline, you can put your Claude traffic behind a service that issues scoped API keys and tracks usage against them automatically. This is the approach SubToAPI takes: instead of one shared Anthropic key, you generate sub_live_... keys per app, environment, or team member, and every request through that key is logged with token counts, model, and timestamp — visible in a dashboard without writing a single logging line.
The setup is just swapping your base URL and key:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Summarize this ticket."}]
}'
Because each key maps to a specific app or teammate, the usage dashboard splits naturally by caller without you tagging requests yourself. If you're running a multi-tenant product or a team where multiple developers share Claude access, this removes the entire "who used what" problem that the DIY approach has to solve manually. Check the quickstart for the full setup and the messages docs for request/response details.
Choosing between the two
Build your own pipeline if:
- You already have observability infrastructure (Grafana, Datadog, a data warehouse) and just need to feed Claude usage into it
- You need custom cost allocation logic specific to your business (e.g., splitting cost by customer account, not by API key)
- You're at a scale where a dedicated gateway adds latency you can't absorb
Use a hosted layer if:
- You want per-key usage and cost breakdowns without writing logging code
- You're issuing Claude access to multiple team members or client apps and want seat-level visibility
- You want streaming, usage metadata, and key management in one dashboard instead of three separate systems — see pricing for plan details
Most teams start with the DIY query above because it's five lines of code, then migrate to a dedicated layer once they have more than two or three consumers of the same Claude key and the "who spent what" question starts needing its own meeting.
Visualizing the data
Whichever path you pick, the dashboard itself is usually one of three things:
- A Grafana panel reading from your Postgres/ClickHouse usage table, bucketed by day and model
- A Metabase or Retool dashboard for non-engineers to review spend
- A built-in dashboard, if you're using a provider-level tool that already aggregates by key
Keep the first version simple: total tokens by day, total tokens by model, and total tokens by caller. Add cost-per-model multipliers once you've validated the raw numbers are correct — token counts are easy to log wrong (forgetting to count cached or system prompt tokens is the most common mistake).
questions
Does the Claude API provide cost data directly, or just token counts? Each response includes token counts (input_tokens, output_tokens), not a dollar cost. You calculate cost yourself using Anthropic's published per-model pricing, or use a layer that computes it for you.
Can I track usage per team member without giving everyone the same API key? Yes — generate a separate key per person or app. With SubToAPI this is built in: each sub_live_... key tracks its own usage, so you get per-seat breakdowns in the dashboard automatically.
What's the minimum data I need to start a usage dashboard? Timestamp, model, input tokens, and output tokens per request. That's enough for a daily cost chart. Add caller ID and latency once you need to debug who's driving spend or slow responses.