Setting Spend Limits and Usage Caps per API Key
Per-key credit limits are hard stops on how much a single API key can spend before OpenRouter returns 402 Payment Required.
Search across all documentation pages
Per-key credit limits are hard stops on how much a single API key can spend before OpenRouter returns 402 Payment Required.
They contain blast radius when an agent loops, a leaked key runs hot, or a tenant goes over plan.
Create or update inference keys with a limit (and optional limit_reset), monitor limit_remaining via GET /api/v1/key, and isolate each agent environment or customer on its own key.
limit and reset policy (daily, weekly, monthly, or no reset - verify allowed values at build).POST/PATCH /api/v1/keys with limit, limit_reset, and optional include_byok_in_limit.GET /api/v1/key with the inference key and abort if limit_remaining is too low.disabled: true) when a limit is hit unexpectedly.import os
import requests
MGMT = os.environ["OPENROUTER_MANAGEMENT_KEY"]
BASE = "https://openrouter.ai/api/v1/keys"
H = {
"Authorization": f"Bearer {MGMT}",
"Content-Type": "application/json",
}
# 1) Create a capped production key
created = requests.post(
f"{BASE}/",
headers=H,
json={
"name": "agent-prod",
"limit": 100.0,
"limit_reset": "monthly",
"include_byok_in_limit": False,
},
)
created.raise_for_status()
body = created.json()
# Secret is shown on create; persist it immediately
print("hash:", body.get("data", body).get("hash") if isinstance(body, dict) else body)
# 2) List keys (paginate with offset)
listed = requests.get(BASE, headers=H, params={"offset": 0})
listed.raise_for_status()
print("keys:", listed.json())
# 3) Inference side: check remaining quota
inf = os.environ["OPENROUTER_API_KEY"]
key_info = requests.get(
"https://openrouter.ai/api/v1/key",
headers={"Authorization": f"Bearer {inf}"},
)
key_info.raise_for_status()
data = key_info.json()["data"]
remaining = data.get("limit_remaining")
if remaining is not None and remaining < 1.0:
raise SystemExit(f"insufficient key budget: {remaining}")
print(
"usage_daily=", data.get("usage_daily"),
"usage_monthly=", data.get("usage_monthly"),
"limit_remaining=", remaining,
)Update an existing key by hash:
key_hash = "<YOUR_KEY_HASH>"
patched = requests.patch(
f"{BASE}/{key_hash}",
headers=H,
json={
"limit": 150.0,
"limit_reset": "daily",
"disabled": False,
},
)
patched.raise_for_status()| Budget | Scope | Failure mode |
|---|---|---|
| Account credits | Whole OpenRouter balance | All keys fail when empty |
Per-key limit | One inference key | That key returns 402; others continue |
Raising a key limit never creates money. You still need account credits.
From GET /api/v1/key (inference key):
limit - cap or null if unlimitedlimit_remaining - residual budgetlimit_reset - reset cadence or nullusage, usage_daily, usage_weekly, usage_monthlybyok_usage* and include_byok_in_limit when using provider keys through OpenRouterUse daily/weekly fields for anomaly detection even when the hard cap is monthly.
Organizations can also use workspace budgets and guardrails for spend and model access (see OpenRouter workspaces/guardrails docs at build).
Per-key limits remain the simplest unit for single-service agents.
limit: null) are footguns in production agents. Prefer an explicit number.include_byok_in_limit.| Control | Granularity | Enforcement |
|---|---|---|
| Per-key credit limit | Key | OpenRouter 402 |
| Account balance only | Account | OpenRouter 402 |
| Application dollar budget | Run / tenant | Your code |
| Workspace budgets | Team/project | OpenRouter (org feature) |
| Provider console limits | Direct API | Provider-specific |
limit?Limits are in OpenRouter credits denominated like USD for pricing purposes. Confirm exact units in the live key API response at build.
Yes via the Management API, but do it behind alerts and approval. Auto-raising without a human can fund infinite loops.
Free variants have separate rate limits. Paid usage decrements credits and key limits. Verify free-tier interaction for your account type at build.
PATCH /api/v1/keys/{hash} with {"disabled": true} using the management key, then rotate a replacement.
Yes. You can set credit limits when creating or editing keys in the OpenRouter keys UI. The API is for automation.
No. Shared keys hide owners and make limits meaningless. Issue per-dev keys with small daily caps.
Budget checks apply to request acceptance. Still design agents to checkpoint state so a later turn 402 can resume after funding.
Documented reset helpers are fixed cadences such as daily/weekly/monthly. For custom periods, automate PATCH from your own scheduler.
Related: Cost & Fallback Basics
Related: Monitoring OpenRouter Spend and Usage in Real Time
Related: Cost-Based Routing: Sending Cheap Tasks to Cheap Models
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