Monitoring OpenRouter Spend and Usage in Real Time
You cannot control agent cost you do not measure. OpenRouter exposes inline usage on every completion, key balance endpoints, generation lookup, and (with a management key) analytics queries.
Search across all documentation pages
You cannot control agent cost you do not measure. OpenRouter exposes inline usage on every completion, key balance endpoints, generation lookup, and (with a management key) analytics queries.
Log usage from each chat response into your metrics backend, poll GET /api/v1/key for remaining budget, and use Activity UI or the Analytics API for model/key rollups when investigating spikes.
generation_id, model, provider (if present), tokens, usage.cost, route tier, agent name, tenant id.usage as the real-time source of truth (always included; legacy usage.include flags are deprecated/no-ops).GET /api/v1/key every N minutes (or before batches) for limit_remaining, usage_daily, and friends./api/v1/analytics/meta then /api/v1/analytics/query) or use the Activity dashboard./api/v1/generation?id=... (path verify at build) for historical cost audit by generation id.import os
import time
import requests
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
def chat_and_meter(messages, model="openai/gpt-4o-mini", **provider):
t0 = time.perf_counter()
resp = client.chat.completions.create(
model=model,
messages=messages,
extra_body={"provider": provider} if provider else None,
)
latency_ms = (time.perf_counter() - t0) * 1000
usage = resp.usage
# OpenAI SDK may expose usage as object; normalize
cost = getattr(usage, "cost", None)
if cost is None and isinstance(usage, dict):
cost = usage.get("cost")
record = {
"id": resp.id,
"model": resp.model,
"latency_ms": latency_ms,
"prompt_tokens": getattr(usage, "prompt_tokens", None),
"completion_tokens": getattr(usage, "completion_tokens", None),
"cost": cost,
}
print("meter", record) # replace with metrics.export
return resp.choices[0].message.content, record
chat_and_meter([{"role": "user", "content": "hello"}], sort="price")
# Key-level remaining budget
key = requests.get(
"https://openrouter.ai/api/v1/key",
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
)
key.raise_for_status()
print("key_budget", key.json()["data"])Analytics rollup (management key; API is beta - verify schema at build):
import os
import requests
from datetime import datetime, timedelta, timezone
mgmt = os.environ["OPENROUTER_MANAGEMENT_KEY"]
headers = {
"Authorization": f"Bearer {mgmt}",
"Content-Type": "application/json",
}
meta = requests.get("https://openrouter.ai/api/v1/analytics/meta", headers=headers)
meta.raise_for_status() # discover metrics/dimensions; do not hardcode forever
end = datetime.now(timezone.utc)
start = end - timedelta(days=7)
query = {
"metrics": ["total_usage", "request_count", "tokens_total", "cache_hit_rate"],
"dimensions": ["model"],
"order_by": {"field": "total_usage", "direction": "desc"},
"time_range": {
"start": start.strftime("%Y-%m-%dT%H:%M:%SZ"),
"end": end.strftime("%Y-%m-%dT%H:%M:%SZ"),
},
"limit": 20,
}
resp = requests.post(
"https://openrouter.ai/api/v1/analytics/query",
headers=headers,
json=query,
)
resp.raise_for_status()
print(resp.json())| Horizon | Source | Use |
|---|---|---|
| Per request (seconds) | Response usage | Live dashboards, unit economics |
| Per key (minutes) | GET /api/v1/key | Cap enforcement, burn alerts |
| Per org (hours/days) | Activity UI / Analytics API | Model mix, tenant keys, regressions |
Inline usage commonly includes:
prompt_tokens / completion_tokens / total_tokenscost - charged amountcost_details.upstream_inference_cost - upstream charge (especially meaningful for BYOK contexts; generation lookup notes differ - verify)For streaming, ignore intermediate chunks without usage; meter the final usage payload.
OpenRouter also exposes credit balance APIs for account-level remaining credits (see credits API reference at build). Use that for org dashboards; use /key for the specific runtime credential.
Store resp.id from completions. Later, generation metadata endpoints let you re-read cost for disputes and audits without trusting only local logs.
Track more than tokens:
A stable token rate with rising calls/task means the agent, not the price sheet, regressed.
metadata.truncated before summing.usage.cost may need model_extra or raw JSON depending on SDK version.| Stack | Pros | Cons |
|---|---|---|
| Inline usage + your APM | True real-time | You build rollups |
| OpenRouter Activity UI | Fast human debug | Not automated |
| Analytics API | Org-scale queries | Management key, beta churn |
| External LLM observability (Langfuse, etc.) | Traces + cost | Extra vendor |
| Provider consoles only | Native discounts view | No multi-model unity |
Yes under current OpenRouter usage-accounting docs. Old usage: {include: true} parameters are deprecated and unnecessary.
Accumulate content from deltas; read usage from the final SSE event or SDK final chunk.
Yes. Poll limit_remaining and alert at 20% / 5% thresholds so humans act before 402s.
Compare today's usage_daily to the 7-day median by key. Alert on 2-3× spikes plus absolute dollar ceilings.
The Activity UI supports filtering by model, provider, and API key. Use it when a single slug's cost jumps after a routing change.
Send stable user/app metadata if you use OpenRouter user-tracking features, and always log your own tenant_id beside usage.cost.
If model fallbacks fire, resp.model may differ from the requested primary. Group spend by served model, and tag requested model separately.
Log usage.cost + model per call, poll /api/v1/key for remaining, and open the Activity page for last 24h by key.
Related: Setting Spend Limits and Usage Caps per API Key
Related: Cost-Based Routing: Sending Cheap Tasks to Cheap Models
Related: Comparing OpenRouter's Per-Model Pricing Against Direct Provider Rates
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026