skills/openrouter-analytics-schema/SKILL.md
Discover the OpenRouter analytics schema — available metrics, dimensions, filter operators, and granularities. Use when you need to know what analytics data is queryable, what dimensions you can break down by, or how to map a user's question to the right metric/dimension combination.
npx skillsauth add openrouterteam/skills openrouter-analytics-schemaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Discover what analytics data is available for querying. The meta endpoint returns live, always-current definitions of metrics, dimensions, filter operators, and granularities.
--api-key <key> or set the OPENROUTER_API_KEY environment variableGET https://openrouter.ai/api/v1/analytics/meta
Authorization: Bearer sk-or-v1-...
Or via the openrouter-analytics skill scripts:
cd <openrouter-analytics-skill-path>/scripts && npx tsx discover-schema.ts
{
"data": {
"metrics": [
{ "name": "request_count", "display_label": "Request Count", "is_rate": false, "display_format": "number" }
],
"dimensions": [
{ "name": "model", "display_label": "Model" }
],
"operators": [
{ "name": "eq", "value_type": "scalar" }
],
"granularities": [
{ "name": "day", "display_label": "Day" }
]
}
}
Each metric has:
| Field | Meaning |
|---|---|
| name | Identifier to use in query requests |
| display_label | Human-readable label |
| is_rate | Whether this is a ratio/rate (averaged, not summed) |
| display_format | How the value should be formatted: number, currency, percent, latency, or throughput |
Most volume and cost metrics support time ranges up to 365 days with daily granularity. Latency/throughput metrics and some dimensions (provider, origin, country, finish_reason, external_user, context_length_bucket, generation_id) are limited to 31-day time ranges. If a query times out, try narrowing the time range or removing latency/throughput metrics and per-generation dimensions.
Volume metrics (how much):
request_count — number of API requests (up to 365 days)tokens_total, tokens_prompt, tokens_completion — token counts (up to 365 days)reasoning_tokens — tokens used for extended thinking (up to 365 days)cached_tokens — tokens served from cache (up to 365 days)byok_request_count — number of BYOK requests (up to 365 days)guardrail_invoked_count — count of requests that triggered guardrails (31-day limit)response_cached_count — count of responses served from cache (31-day limit)Cost metrics (how much money):
total_usage — total cost in USD (up to 365 days)byok_usage — BYOK (bring your own key) inference cost in USD (up to 365 days)credits_usage — credits-based usage in USD (31-day limit)usage_upstream — provider-side (upstream) cost in USD (up to 365 days)usage_cache — cache cost component in USD (up to 365 days)usage_data — data logging cost adjustment in USD; typically negative when a data logging discount applies (up to 365 days)usage_web — web search cost in USD (up to 365 days)usage_upstream_web — provider-side web search cost in USD (up to 365 days)usage_file — file processing cost in USD (31-day limit)usage_upstream_file — provider-side file processing cost in USD (31-day limit)usage_web_fetch — web fetch cost in USD (31-day limit)usage_upstream_web_fetch — provider-side web fetch cost in USD (31-day limit)Performance metrics (how fast):
avg_latency, p50_latency, p90_latency, p99_latency — response latency in millisecondsavg_throughput, p50_throughput, p90_throughput, p99_throughput — tokens per secondEfficiency metrics (how well):
cache_hit_rate — ratio of cached tokens to prompt tokens (0–1)guardrail_invoked_rate — ratio of requests that triggered guardrailsresponse_cached_rate — ratio of responses served from cacheEach dimension has:
| Field | Meaning |
|---|---|
| name | Identifier to use in query requests |
| display_label | Human-readable label |
Dimensions are what you break down by — "show me spend by model" means dimensions: ["model"].
You can combine up to 2 dimensions in a single query (e.g., ["model", "provider"]).
Some dimensions have their raw IDs automatically resolved to human-readable labels in query results. Data rows contain the resolved display names directly:
| Dimension | Resolved to |
|---|---|
| api_key_id | Key name/label |
| app | App title or origin URL |
| user | User name or email address |
| workspace | Workspace name |
All other dimensions (e.g., model, provider, country) are returned as-is without resolution.
Rows with an empty
uservalue represent traffic not attributed to a specific org member (e.g., API keys created at the org level).
Available with all time ranges:
model — the OpenRouter model ID (permaslug)variant — model variant (e.g., standard, extended)api_key_id — which API key made the requestuser — the creator user ID (for org-level queries)Limited to 31-day time ranges:
generation_id — unique ID for each generation (use to drill down to individual requests, then inspect via the openrouter-generations skill)provider — upstream provider nameorigin — request origin/sourcecountry — request countryfinish_reason — why the generation ended (stop, length, etc.)workspace — workspace IDapp — application IDexternal_user — custom user ID passed by the callercontext_length_bucket — bucketed context length (1K, 10K, 100K, etc.)Filter operators for the filters array in query requests:
| Operator | Value Type | Meaning |
|---|---|---|
| eq | scalar | Equals |
| neq | scalar | Not equals |
| gt | scalar | Greater than |
| gte | scalar | Greater than or equal |
| lt | scalar | Less than |
| lte | scalar | Less than or equal |
| in | array | In list |
| not_in | array | Not in list |
Time bucketing for time-series queries:
| Granularity | Use when |
|---|---|
| minute | Last few hours, real-time monitoring |
| hour | Last 1–3 days |
| day | Last week to 3 months |
| week | Last 3–12 months |
| month | Year-scale trends |
When no granularity is set, the query returns aggregate totals without time bucketing.
Use this guide to translate natural-language questions into the right metric/dimension/filter combination:
| Question pattern | Metrics | Dimensions | Notes |
|---|---|---|---|
| "How much did I spend?" | total_usage | — | Add granularity for trends |
| "Which models cost the most?" | total_usage | model | Order by total_usage desc |
| "How many requests?" | request_count | — | Add model or api_key_id for breakdown |
| "How many tokens?" | tokens_total | — | Use tokens_prompt / tokens_completion for split |
| "Which provider is fastest?" | avg_latency, p90_latency | provider | 31-day limit |
| "What's my cache hit rate?" | cache_hit_rate | model | Rate metric — shows per-model caching |
| "Which API key uses the most?" | request_count, total_usage | api_key_id | — |
| "Usage over time" | request_count or total_usage | — | Set granularity: "day" |
| "Latency trends" | p90_latency | — | Set granularity: "hour", 31d limit |
| "Usage by country" | request_count | country | 31-day limit |
| "How can I save money?" | total_usage, cache_hit_rate, tokens_total | model | See cost optimization in openrouter-analytics skill |
| "Show me individual requests" | total_usage, tokens_total | generation_id | 31-day limit. Use returned IDs with openrouter-generations skill for full metadata and content |
| "How much BYOK spend?" | byok_usage | model | Up to 365 days |
| "BYOK vs credits split?" | byok_usage, credits_usage | — | credits_usage limited to 31 days |
| "How many guardrail triggers?" | guardrail_invoked_count, guardrail_invoked_rate | model | 31-day limit |
| "How many cached responses?" | response_cached_count, response_cached_rate | model | 31-day limit |
| "Where does my spend go?" | usage_upstream, usage_cache, usage_data | — | Full cost breakdown (up to 365 days) |
| "Web search costs?" | usage_web, usage_upstream_web | model | Up to 365 days |
| "File processing costs?" | usage_file, usage_upstream_file | model | 31-day limit |
| "Web fetch costs?" | usage_web_fetch, usage_upstream_web_fetch | model | 31-day limit |
group_limit (1–10,000): controls max rows per dimension combination. Auto-computed on time-series queries with dimensions to guarantee full time-window coverage. Set explicitly to cap per-group rows (e.g., top N per model per day).development
Answer natural-language questions about a user's OpenRouter usage data — spend, request volume, model breakdown, latency, token usage, and cost optimization. Use when the user asks about their API usage, billing, costs, top models, traffic patterns, or wants to optimize their OpenRouter spend.
development
Construct and execute analytics queries against the OpenRouter API — full parameter reference for metrics, dimensions, filters, time ranges, ordering, and pagination. Use when building or debugging an analytics query, understanding the request/response shape, or handling query errors.
development
Retrieve detailed metadata and stored content for individual OpenRouter generations. Use when the user wants to inspect a specific request — its cost, latency, token usage, provider routing, or the actual prompt/completion text — or is debugging a failed or unexpected generation.
development
Transcribe speech to text using OpenRouter's speech-to-text API. Use when the user asks to transcribe audio, convert speech to text, extract a transcript from a recording or meeting, caption a video's audio, or mentions STT, speech-to-text, ASR, or transcription.