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

# Budgets

> Cap spend at the org, team, user, virtual key, or agent level. How budgets attach, how enforcement works, and how to set one up.

A budget caps how much a scope can spend on LLM calls. ForceAI tracks the cost of every request in the spend logs and rejects a request once the applicable budget is exceeded. Budgets attach directly to orgs, teams, users, and virtual keys; agents inherit theirs from the key they run under, and access groups do not carry a budget at all

## Where a budget can live

| Scope        | Own budget?              | How                                                                                                          |
| ------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| Virtual key  | Yes, most granular       | `max_budget` on the key, with `budget_duration`                                                              |
| Team         | Yes                      | `max_budget` on the team; every key and member in the team shares it. A team is the "group budget" primitive |
| User         | Yes                      | `max_budget` on the internal user                                                                            |
| Org          | Yes, via a Budget object | the org references a reusable Budget (`budget_id`)                                                           |
| Agent        | No, inherits             | an agent runs under a virtual key ("Owned By: Agent"); its budget is the `max_budget` on that key            |
| Access group | No                       | access groups gate which models, agents, skills, and MCP servers a key may use, not spend                    |

<Info>
  There is no per-access-group budget. To budget a group of keys, put them in a team and set the team's `max_budget`, or point them all at one shared Budget object
</Info>

## How enforcement works

Every request arrives on a virtual key, and that key belongs to a user, a team, and an org. ForceAI checks the request against every level that has a budget, and the tightest limit that is already exceeded blocks it. So a key can be under its own cap yet still be rejected because its team's monthly cap is used up. The error is explicit, for example:

```
Budget has been exceeded! Team=... Current cost: 0.000205, Max budget: 0.0002
```

Three modifiers apply on any level:

* `budget_duration` sets a reset window (`1h`, `30d`, `1mo`, and so on). Spend resets at `budget_reset_at`, which gives you recurring budgets
* `soft_budget` is an alert threshold, not a block. You get notified but requests keep flowing
* `model_max_budget` sets per-model caps within one scope, for example `{"gpt-4": 10, "claude-haiku-4-5": 100}`

<Warning>
  Enforcement is near-real-time, not instantaneous. Spend is flushed to the database on an interval, so a burst of requests can briefly run past the cap before the next request is blocked. Budgets are a spend guardrail, not a hard transaction limit
</Warning>

## The Budgets page

The dashboard **Budgets** page manages reusable Budget objects: a named budget with a max, an optional duration, and optional per-model caps. Create one there, then attach it to an org (or reference it from a key) instead of retyping the same limits everywhere

## Set a budget

<Steps>
  <Step title="On a virtual key">
    Set a max budget and duration when you create or edit the key. By API:

    ```bash theme={null}
    curl -X POST http://localhost:4001/key/generate \
      -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
      -d '{"key_alias": "reporting-bot", "max_budget": 20, "budget_duration": "30d", "models": ["claude-haiku-4-5"]}'
    ```
  </Step>

  <Step title="On a team (the group budget)">
    ```bash theme={null}
    curl -X POST http://localhost:4001/team/new \
      -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
      -d '{"team_alias": "growth", "max_budget": 500, "budget_duration": "30d"}'
    ```

    Every key created in that team draws down the one team budget
  </Step>

  <Step title="On an org">
    ```bash theme={null}
    curl -X POST http://localhost:4001/organization/new \
      -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
      -d '{"organization_alias": "acme", "max_budget": 5000, "budget_duration": "30d"}'
    ```

    Teams and keys created under the org all count toward it
  </Step>

  <Step title="On an agent">
    An agent uses a virtual key, so budget the key it runs under. Create the key with the agent as owner (Virtual Keys -> Create Key -> Owned By: Agent) and set its `max_budget`, or create a service-account key with a budget and attach it to the agent
  </Step>
</Steps>

## Verify a budget blocks

Set a tiny budget, spend past it, and the next request is rejected. Against a team with `max_budget: 0.0002`:

```bash theme={null}
# create the team + a key in it, then send small requests until it blocks
for i in $(seq 1 8); do
  curl -s http://localhost:4000/v1/chat/completions \
    -H "Authorization: Bearer $TEAM_KEY" -H "Content-Type: application/json" \
    -d '{"model": "claude-haiku-4-5", "messages": [{"role": "user", "content": "say hi"}]}' \
    | jq -r '.error.message // "ok"'
  sleep 5
done
```

Once cumulative spend crosses the cap you get `Budget has been exceeded! Team=... Current cost: ... Max budget: 0.0002`, and because the budget is on the team, a brand-new key in that team is blocked immediately too

<Info>
  Use a very small `max_budget` and allow a few seconds between requests so spend flushes; otherwise a rapid burst may run slightly past the cap before the block engages
</Info>
