> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aireserve.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Budgets

> Cap what each member, each team, or your whole organization can spend. Two clicks in the portal or one API call; the gateway refuses the request that would cross the line.

Your organization has one wallet. Budgets decide who may spend how much of it. A budget is a
dollar amount on a **member**, a **team**, or the **organization**; once that subject's spend
reaches it, the gateway refuses the subject's next request before it reaches a model, and
keeps refusing until an admin raises the budget. Nothing else changes: routing, prices and
keys stay as they are.

Budgets are set on people and teams, not on API keys. A personal key acts as its owner and a
team key as its team, so a budget on a person or a team covers their keys too.

## Set a budget for one member

**1. Open Members**

In the portal sidebar, open **Organization → Members**
([portal.aireserve.com/org](https://portal.aireserve.com/org)). You need the enterprise admin role.

**2. Pick the person**

In the **Users** view, people are grouped by team. Open the row menu (⋯) on the member and choose **Set Budget**.

**3. Enter the amount**

**Budget Limit (USD, lifetime)** is the total this person may spend from now on, across everything they use.
Optionally add **Requests/minute** and **Requests/day** to rate-limit them as well. Save.

**4. Done**

The budget applies to the member's next request (within 30 seconds on every gateway instance). The **Budget** column
of the Users table now shows their spend against the budget and reads **Budget reached** once they are at the limit
(the Org Chart shows the same as a badge on the person). Open the same menu again to edit the amount (the dialog
shows their current spend) or to **Remove budget**.

Three things to know:

* **Lifetime, not monthly.** Every budget set from the portal or the admin API is an
  allocation, like cash in an envelope: it does not reset on the first of the month. To give
  someone more room, raise the number.
* **\$0 stops a person now.** A zero budget refuses the next request. Use it to pause a member
  without deactivating their account or revoking their keys; raise or remove it to let them
  spend again.
* **Removing a budget is not "unlimited".** A member without a budget of their own is still
  stopped by their team's budget and by the organization's, whichever of those are set. A
  member with no team has only the organization budget above them (see the Unassigned pool
  below).

### What counts against a member's budget

Every metered request that runs **as that person**: chat in the portal, coding tools signed
in with their account, and API keys scoped to them. Each request counts at the price your
organization is billed for it, after prompt-cache discounts. Team keys count against the team
budget and organization-wide keys against the organization budget only; neither is attributed
to a person.

## How budgets stack

Three levels, each carved out of the one above it.

| Level | Where to set it | Who can set it | Covers |
| - | - | - | - |
| Organization | Members → **Organization controls** → **Organization budget** → **Set budget** | Enterprise admins | Every metered request the organization makes |
| Team | The pencil (**Set budget**) on a team's card in the **Users** view, or on the team in the **Org Chart** | Enterprise admins; managers, for teams strictly below their own | The team's members plus every sub-team's budget |
| Member | Row menu (⋯) → **Set Budget** | Enterprise admins | One person's chat, coding tools and personal keys |

The portal enforces the stacking when you type a number:

* A team's budget comes out of its parent's (a top-level team's out of the organization's).
  You cannot allocate more than the parent has left; the dialog shows the maximum. A team
  with sub-teams shows its **total** (including sub-teams) and the **direct** amount left for
  its own members.
* A member's budget cannot exceed their team's, and the member budgets inside one team cannot
  add up to more than the team's budget. The error names the gap: *"Engineering has \$800.00 of
  \$1,000.00 allocated to user caps; this cap would exceed it by \$300.00."* A team with no
  budget of its own places no such limit.
* Members without a team sit in the **Unassigned** pool. Its budget is a planning ceiling,
  not a request-time limit: member budgets inside the pool are validated against it and it
  raises the 90% alert, but it refuses no request on its own. A team-less member is stopped
  only by their own budget or by the organization's, so give such members a budget of their
  own if the pool ceiling has to hold.
* Managers (the **Manager** toggle on a member) get a team of their own and can divide the
  budget they were given among the teams below them. They cannot set member budgets, and
  members can see their own budget but nobody else's.

At request time every level is checked, most specific first. A member who is under their own
budget can still be refused because their team or the organization is at its limit; the API
message says which one.

## What happens at the limit

Before a request is sent to a model, the gateway checks the caller's member, team and
organization budgets. A request is admitted only while committed spend plus the estimated
cost of that subject's requests already in flight is under the budget. The request that would
cross the line is refused: it never reaches a model, and you are not charged for it. A
response that is already streaming finishes.

The refusal is a client error that says who hit which budget and what to do:

> User budget reached for Jane Doe. Contact your administrator to raise the limit.

A team limit reads *"Team budget reached for Platform…"*, an organization limit *"Budget
reached for your organization…"*.

| Surface | Status and code |
| - | - |
| Every OpenAI-compatible route (`/v1/chat/completions`, `/v1/responses`, images, video, speech) | `402` with `type: usage_cap_error`, `code: usage_cap_exceeded` |
| Anthropic-compatible `/v1/messages` | `402` with `type: billing_error` |
| Bedrock-compatible `/model/…/converse` (AWS SDKs) | `429 ThrottlingException` from the gateway edge (the AWS dialect has no 402). An AWS SDK retries it a few times before surfacing it, so the refusal shows up as a short delay, then the error. |
| Coding tools | The same sentence, shown in the tool |
| Portal chat | The same sentence, shown in the conversation |

On the `/v1` routes a budget refusal carries no `Retry-After` and the AI Reserve SDKs never
retry it: the limit does not lift on its own. The full error shapes are in
[Errors](https://docs.aireserve.com/api-reference/errors.md#status-codes-and-error-codes).

## Alerts and visibility

* **Admins are emailed at 90%.** When a member, a team, or the Unassigned pool passes 90% of
  its budget, every enterprise admin of the organization receives *"Budget alert: Jane Doe is
  at 94% of its budget"*, once per crossing, within about 30 seconds of the spend that crossed
  it. The same subjects appear on the **Needs attention** card of your organization's overview.
* **The Members page shows the numbers.** Each capped member's spend against their budget in
  the **Budget** column; each team card's spend against its budget in the header. **Analytics**
  breaks spend down by member, team, model and key.
* **Members see their own.** A capped member has a quiet *"\$X of \$Y"* line in the account
  menu at the bottom of the sidebar; it turns amber past 80%. It informs and never blocks.

## From the API, the CLI or a coding agent

Every budget action is an [admin API](https://docs.aireserve.com/capabilities/admin-api.md) operation: callable over HTTP
with a management token, from the `aireserve` CLI, or as an MCP tool with the same name. Find
the member's id with `list_org_users`.

```bash curl theme={"dark"}
curl https://api.aireserve.com/v1/admin/set_user_spend_cap \
  -H "Authorization: Bearer $AIRESERVE_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"userId": "9cba8ede-…", "budgetLimitUsd": 50, "requestsPerMinute": 60}'
```

```shell CLI theme={"dark"}
aireserve admin teams-budgets set-user-spend-cap --user-id 9cba8ede-… --budget-limit-usd 50 --requests-per-minute 60
aireserve admin teams-budgets list-user-spend-caps
aireserve admin teams-budgets remove-user-spend-cap --user-id 9cba8ede-…
```

```text Coding agent (MCP) theme={"dark"}
"Give Jane a $50 budget and 60 requests a minute."
"Who is over 80% of their personal budget right now?"
```

```json theme={"dark"}
{
  "status": "executed",
  "ok": true,
  "summary": "Set Jane Doe's spend cap to $50.00 (currently uncapped)",
  "message": "Jane Doe's spend cap set to $50.00"
}
```

The budget operations, all admin-only unless noted:

* `set_user_spend_cap`: set a member's budget (`userId`, `budgetLimitUsd`, optional
  `requestsPerMinute` and `requestsPerDay`).
* `list_user_spend_caps`: every member with a budget or a personal rate limit, with lifetime
  spend; anyone absent has neither.
* `remove_user_spend_cap`: drop a member's budget; they fall back to team and organization
  limits.
* `set_team_cap`: set a team's total allocation (`teamId`, `budgetLimitUsd`). Managers may
  call it for teams below their own.
* `set_unassigned_pool_cap`: the budget for members without a team.
* `set_client_spend_cap`: set or clear the organization budget (`capUsd`; `null` clears).
  Asks for confirmation.
* `get_team_allocations`: the allocation table, with the organization budget and each team's
  budget, spend and headroom.
* `get_my_budget_status`: the caller's own budget, lifetime spend and remaining headroom,
  plus their team's budget and this month's team spend. Available to every member of an
  organization.

The complete list, with every field, is in the
[operation reference](https://docs.aireserve.com/connect/mcp-tools.md#teams-budgets).

## Verify it yourself

A five-minute check that the limit is real, on a test member whose key you hold:

**1. Set a tiny budget**

Give the member a **\$0.10** budget (row menu → **Set Budget**).

**2. Spend past it**

Send a few chat completions with the member's key. Each succeeds while their spend plus in-flight estimates is under
\$0.10.

**3. See the refusal**

The next request answers `402 usage_cap_exceeded` with *"User budget reached for …"*, no `Retry-After`, no charge.
The **Budget** column reads **Budget reached**. Admins receive the alert email once the member's committed spend
passes 90% of the budget, so with a \$0.10 budget expect it only if the refused request landed above \$0.09.

**4. Raise it**

Edit the budget upward. The next request succeeds within 30 seconds, without touching the key.

> [!NOTE]
>
> Budgets cap spend that is **metered per request through the gateway**. Three things sit outside them: inference on
> your own [dedicated GPU endpoints](https://docs.aireserve.com/capabilities/dedicated-gpu-endpoints.md) (billed by time, not per request), your own
> provider accounts used through [BYOK](https://docs.aireserve.com/capabilities/byok.md), and the per-session budgets a developer sets on a coding
> session (`SESSION_BUDGET_EXCEEDED`). Each has its own page.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.