Key budgets
Cap what an API key may spend on inference per day, per month or in total, and how requests near the limit are handled.
An API key can carry a spend budget: the most it may spend on inference in total, per UTC day, or per UTC month. Give each agent its own key with a budget and a misbehaving agent stops at its limit instead of draining the organization's balance.
A budget caps the key, not the organization: the key still needs a funded balance, and the organization's other keys are unaffected.
Set a budget
Pass budget when you create the key. Amounts are integer nanoUSD
(1 USD = 1,000,000,000 nanoUSD):
curl -X POST https://api.openrelay.inc/v1/orgs/{orgId}/api-keys/create \
-H "Authorization: Bearer $OPENRELAY_SESSION_OR_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "triage-agent", "budget": { "limitNanoUsd": 50000000000, "period": "monthly" } }'{
"id": "key_123",
"key": "or_…",
"name": "triage-agent",
"budget": {
"limitNanoUsd": 50000000000,
"period": "monthly",
"spentNanoUsd": 0,
"periodEndsAt": "2026-11-01T00:00:00Z"
}
}period | Resets |
|---|---|
lifetime (the default) | never |
daily | at 00:00 UTC |
monthly | at 00:00 UTC on the first of the month |
With the CLI: orl api-keys create --name triage-agent --budget-usd 50 --budget-period monthly.
A key that carries a budget cannot create keys, so it cannot mint itself one without a budget.
Change a budget
With permissions enabled, a signed-in member changes a
budget through
PATCH /v1/orgs/{orgId}/api-keys/{id}. A key
never changes its own budget.
{ "budget": { "limitNanoUsd": 80000000000 } }budget changes the fields it names, and a field left out keeps its value:
- A new
limitNanoUsdalone keeps the period and what was spent so far in it. - A new
periodkeeps the limit and counts from zero. "limitNanoUsd": 0removes the budget. A budget set again later counts from zero.- A key without a budget needs
limitNanoUsdto get one.
Without permissions, a budget is fixed when the key is created: to change it, create a key with the new budget and revoke the old one.
A change applies to the key's next request, usually at once: the update clears the key's cached authentication record. A request that reloads that record while the update lands, or a clear that fails, can keep the old budget in use for up to a minute. Requests already running count toward the budget they were admitted with.
What counts
- Every inference request the key makes, at the price it is billed: the
openrelay.cost_nano_usdfigure on the response (Pricing & billing). - Batches the key submits, at the batch price, counted as the batch's records are billed when it finishes.
- Spend counts from when the budget is set. What the key spent before it had a budget does not count.
- Compute is not counted. VMs and pods the key creates spend nothing against its budget.
When the budget runs out
Before a request runs, the API checks the key's spend in the current period plus
an estimate of the request's cost: its prompt, sized from its bytes, at the
input price, plus max_tokens (or the model's default output cap when you send
none) at the output price. If that would pass the limit, or the spend has
already reached it, the request is refused with 402 Payment Required before it
reaches a model:
{
"error": {
"message": "this API key's spend budget is used up; it resets at 2026-11-01T00:00:00Z",
"type": "insufficient_quota",
"code": "key_budget_exceeded"
}
}A request refused for its estimate alone says so; set max_tokens so a
request's estimate fits what is left. Creating a batch is refused the same way
once the budget is used up. Do not retry a key_budget_exceeded unchanged: wait
for the reset, or ask whoever manages the key to raise the budget.
A budget can be passed
The estimate is not a bound, and nothing is reserved while a request runs.
- A single request can cost more than its estimate, so it can pass the limit
by more than the estimate left room for: the prompt's size is estimated from
its bytes and can hold more tokens, cache writes are not priced into the
estimate, and without
max_tokensthe estimate uses the model's default output cap. - Requests admitted at the same time are each checked against the same spend, so each of them can pass the limit.
- A batch is checked only when it is created, and only for a budget that is used up, so one batch can pass the limit by its whole cost. It finishes, and its cost counts toward the key.
A request that was admitted finishes and is billed. Once the recorded spend reaches the limit, every new request and batch is refused.
Check a key's budget
GET /v1/whoami with the key returns its budget on the key object, with what
it has spent this period and when the period ends. orl auth status prints the
same line, and orl doctor warns once the budget is used up:
budget: $12.40 of $50.00 spent (monthly, resets 2026-11-01 00:00 UTC)The key list returns each active key's budget
and spend the same way. If the spend cannot be read for a moment, the budget
comes back without spentNanoUsd, and orl prints "spend unavailable".
Pricing & billing
How inference is billed, a prepaid balance, per-token metering with distinct input, cached-input, and output rates, and the usage and cost on every response.
Errors & rate limits
How the Inference API reports errors, the OpenAI-style error body, the status codes you'll see, and how to retry.