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

# Spend caps, budget alerts, and auto-cutoff

> Set org-level spending ceilings in Orbit: monthly-budget percentage, exact amount, daily spend, and balance-floor rules trigger real-time email/SMS alerts and can automatically pause or block outbound traffic when a threshold trips.

# Spend caps, budget alerts, and auto-cutoff

Orbit's spend controls answer one customer question end-to-end: **how do you stop the wallet from running away without a human on watch.** Pick the ceiling you care about — a percentage of your monthly budget, an exact month-to-date spend amount, today's spend, or a balance floor — and configure an alert rule for it. The rule watches your usage in real time, fires email and/or SMS to the recipients you choose the moment the threshold trips, and — when you pick one of the two enforcement actions — automatically pauses or blocks the org's outbound sending so a runaway burn can't stack up another invoice in the five minutes you weren't reading email.

With this in place, thresholds are opt-in and org-owned: you set the rule, the recipient list, the action, and the cooldown, and no Devotel support ticket is required to change any of it.

***

## 1. Alert rules — your org's thresholds

Create and read the rules under **Billing → Alerts**, or via the API:

* `GET /api/v1/billing/alerts` / `GET /api/v1/billing/alerts/:id` — list and read rules.
* `POST /api/v1/billing/alerts` — create one.
* `POST /api/v1/billing/alerts/:id/test` — dry-run a rule against today's metrics without stamping it or pausing anything.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/billing/alerts \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "80% of monthly budget — page me, then pause",
    "threshold_type": "spend_percent",
    "threshold_value": 80,
    "currency": "USD",
    "notify_emails": ["ops@example.com"],
    "notify_sms_numbers": ["+15551234567"],
    "action_on_hit": "pause_outbound",
    "cooldown_hours": 24
  }'
```

| Field                                  | Notes                                                                                                                                                                                                                                                                                                                                                               |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                                 | Free-text label shown in the dashboard and in the notification subject.                                                                                                                                                                                                                                                                                             |
| `threshold_type`                       | One of `spend_percent` (0–100 of `monthly_budget_cents`), `spend_amount` (cumulative month-to-date spend in cents), `balance_remaining` (current balance in cents), `daily_spend` (today's spend in cents).                                                                                                                                                         |
| `threshold_value`                      | For `spend_percent`, a whole-percent number 1–100; for the other three types a positive integer in cents. The comparison is observed-**greater-or-equal** for the first three, and observed-**less-than** for `balance_remaining`.                                                                                                                                  |
| `currency`                             | ISO 4217 — the wallet's currency.                                                                                                                                                                                                                                                                                                                                   |
| `notify_emails` / `notify_sms_numbers` | Optional recipient lists. Both can be empty when the alert's purpose is pause/block rather than notification. An SMS recipient requires a verified number on your org's messaging surface.                                                                                                                                                                          |
| `action_on_hit`                        | What to do when the threshold trips. `notify` (default) = emails/SMS only, no traffic change. `pause_outbound` = also set `outbound_paused` so new sends return 402 until the alert is cleared in the dashboard. `block_outbound` = also set `outbound_blocked` — a stronger stop used when the envelope needs an operator to review before the org can send again. |
| `cooldown_hours`                       | Debounce — the interval between repeat notifications for the same rule. You rarely need less than an hour; raising it is the counter-medication to "the alert emails every time I blink".                                                                                                                                                                           |

`spend_percent` requires `monthly_budget_cents` on the org to be meaningful. With no budget set, the rule reports itself inapplicable and never fires — and until you set a budget the dashboard disables the percent option with a "Set a monthly budget first" pointer. Set the budget on **Billing → Alerts** in the monthly-budget-cap card (the same value Settings → Account → General edits).

## 2. What happens when a rule trips

The billing alert scheduler evaluates enabled rules on a 10-minute tick. The moment a threshold crosses, three things happen:

1. **Notifications go out.** Every email and SMS recipient receives one message per firing, with the rule's name, the threshold descriptor, and the observed value (e.g. "Observed 82.4% against a threshold of 80% of monthly budget").
2. **`last_triggered_at` is stamped.** Until the cooldown expires the same rule stays quiet — the 10-minute tick never turns into a notification storm while spend hovers just above the line.
3. **The action fires (if you chose one).** `pause_outbound` sets `outbound_paused = TRUE` in a single UPDATE and immediately invalidates the cached outbound-flags entry across every API pod, so the send pipeline re-reads the flag on the next send call — not up to five minutes later. `block_outbound` does the same against the stricter `outbound_blocked` flag.

Outbound sends while paused return `SENDING_PAUSED` (HTTP 402). The wallet header and the dashboard settings read flag the org as paused, and **Billing → Alerts → clear the alert** (or the same POST to the alert's record) re-arms outbound.

## 3. Self-serve daily agent spend cap

Separate from the org-wide rules, an AI-agent owner can pin a hard ceiling on agent LLM spend in USD per UTC day. When the cap trips the runtime gate refuses new agent runs with `AGENT_DAILY_SPEND_CAP_REACHED` (HTTP 429) until midnight UTC or you raise the cap.

* `GET /api/v1/settings/agents/spend-cap` — read the cap, today's spend so far, and the server-computed `cap_reached` flag in one payload.
* `PUT /api/v1/settings/agents/spend-cap` — set or clear it. `null` removes the cap entirely.

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/settings/agents/spend-cap \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "daily_spend_cap_cents": 50000 }'
```

The sentinel value range is 1 cent to \$10,000 per UTC day, denominated in USD (the same ledger the agent billing events write to), and is not converted to a tenant wallet currency.

## 4. Sub-account kill-switch — reseller budgets as a hard latch

Resellers pin `monthly_spend_cap_cents` on each child (sub)account and the per-sub-account scheduler watches the month-to-date rollup per child. The kill-switch latch trips at 100% of cap and — unlike the monthly notification-only rules — stays tripped for the rest of the UTC billing month, so a spend runaway stopping short of the reseller's notice is still cut off. A new UTC month re-arms every sub-account automatically; a refund that pulls a child back under its cap releases the latch on the same tick that discovers it.

You do not have to do anything to get the auto-cutoff; it follows from the reseller's per-sub-account cap the same way the monthly org rules follow from your own alert rules.

## 5. Cooldowns — how repeat trips debounce

* `cooldown_hours` on an org rule anchors a repeat-notification silence. Stamp + cooldown window = a jittery threshold emits at most one email/SMS per window, not once per 10-minute tick.
* The per-sub-account kill-switch re-arms per UTC billing month automatically — a latch written last month is invisible to this month's gate.
* The agent daily cap re-arms at UTC midnight. Raising the cap via `PUT /settings/agents/spend-cap` re-arms the gate immediately rather than waiting for the next UTC boundary.

## 6. Dashboard ↔ API parity

Everything the API exposes shows up in the dashboard, with owner/admin roles the same on both:

* **Billing → Alerts** — create/read/test-fire the four threshold types, configure email/SMS recipients, pick the action, pick the cooldown. The monthly-budget cap lives ON THIS PAGE in a dedicated card — the percent-of-budget denominator — with an inline editor, so you can set or clear the cap without leaving Billing. (The same value is also editable under Settings → Account → General, where the full org settings form lives; both surfaces write the same value.)
* **Billing → Balance** — the header widget and the balance-read endpoint both display the org's current outbound-paused flag so operators see a cut-off org before they see the pause error on a send.
* **Settings → Agents** — the agent-spend-cap card on the settings surface, plus an auto-pause banner on the agents list when `cap_reached` is true.

The matching API endpoints are identical to the tables on the dashboard; anything you build against `GET /billing/alerts` reads the same rules the UI writes.

`spend_percent` remains disabled while the budget is null — pick **Billing → Alerts** to configure it, or pick a `spend_amount` / `balance_remaining` / `daily_spend` threshold type instead.

***

For the endpoint-by-endpoint error and schema reference see the [Billing API reference](/api-reference/billing).
