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

# Spend and caps

> How compute and storage accrue, how to cap spend per sandbox and per day, and how to read usage by repo, branch, PR, member, sandbox or model.

Zode bills two things: compute while a sandbox runs, and storage while it exists. AI provider calls are shown but never billed. Prices are on [Pricing](https://docs.zode.dev/pricing.md).

## How billing accrues

* **Compute** accrues per vCPU-hour, only while the sandbox is `running`, prorated to the second with no minimum. A 4 vCPU sandbox running for one hour uses 4 vCPU-hours. Every other status, including `stopped`, costs \$0 compute.
* **Storage** is free for the first 48 hours of every sandbox, forks included. After that it accrues per GB-month until the sandbox is deleted, stopped or not. A month is a fixed 730 hours, and a GB is 10^9 bytes. Storage is metered on the sandbox's provisioned disk size (50 GB for `small`), not on the bytes used.
* **AI** calls through the host proxy are priced at the provider's list price and reported. You pay your provider; Zode adds nothing. See [Agents](https://docs.zode.dev/concepts/agents.md).

Money in the API is integer micro-dollars: 1 USD = 1,000,000. Cents appear only on invoices.

Each UTC day closes one hour after midnight. A closed day is stored once and never recomputed, so past numbers do not move.

### Included usage and credit

Pro includes $20 of usage a month (no rollover). Your Personal workspace starts with a one-time $10 credit, no card needed; a team workspace gets its \$10 when its first card is saved. Included usage is used first, then credit, and both cover compute and storage, never the plan fee.

What happens when credit runs out depends on whether the workspace has a card on file:

* **With a card**, nothing stops. Sandboxes keep running, and usage past what is included goes on that month's invoice.
* **Without a card**, once remaining credit is \$0 or less, creating, forking and starting sandboxes fail with HTTP 402 `credit_exhausted`, and running sandboxes are stopped (hibernated, never deleted) within about 15 minutes. Add a card or buy credit in Billing to lift the block, then start them again. Enterprise is exempt.

You can add credit or turn on auto top-up in Billing: when free credit falls below your threshold, Zode charges your card $5 to $1,000, at most three times a UTC day.

### Low-balance events

A `balance.low` event goes to your [alerts](https://docs.zode.dev/concepts/alerts.md) and [webhooks](https://docs.zode.dev/concepts/webhooks-and-telemetry.md) once when free credit drops below the workspace's low-balance threshold. The threshold is `caps.low_balance_micros` in `PATCH /v1/proxying/settings`, \$2 by default. It fires again only after credit is back at or above the threshold. A workspace without a card also gets one each time its sandboxes are stopped for running out of credit.

```json theme={null}
{
  "reason": "No credit left and no payment method on file: 2 running sandbox(es) stopped, none deleted. Add a card or buy credit in Billing to start them again.",
  "balance_micros": 0,
  "threshold_micros": 2000000,
  "exhausted": true,
  "sandboxes_stopped": ["sbx_q3vfn7tkx2mhcw4a", "sbx_r7k2wbn6tdyx3lpe"]
}
```

`sandboxes_stopped` is present only when sandboxes were stopped.

## Cap a sandbox

`max_cost_micros` caps the AI spend of one sandbox. It counts only AI calls the sandbox makes through Zode's AI proxy on the workspace's keys, never compute or storage. Set it at create or fork; a fork without one keeps its parent's. The host keeps the running total in memory, so a host restart starts it again from zero.

```ts TypeScript theme={null}
import { Sandbox } from "@zodedev/sdk";

const sb = await Sandbox.create({ maxCostMicros: 2_000_000 }); // $2
```

```bash curl theme={null}
curl -s https://api.zode.dev/v1/sandboxes \
  -H "Authorization: Bearer $ZODE_TOKEN" -H "Content-Type: application/json" \
  -d '{"vcpus": 2, "max_cost_micros": 2000000}'
```

```bash CLI theme={null}
zode new --max-cost 2
```

`zode new` and `zode fork` take `--max-cost` in dollars, such as `5` or `2.50`.

When the sandbox's AI spend reaches the cap, the host refuses its next AI calls with HTTP 402 `zode_spend_cap`, and a `spend.cap_reached` event goes to your [alerts](https://docs.zode.dev/concepts/alerts.md) and [webhooks](https://docs.zode.dev/concepts/webhooks-and-telemetry.md) once. The sandbox keeps running and its compute is not counted against this cap.

## Cap the workspace

Owners and billing members set two caps with `PATCH /v1/billing` (also in the console, Billing). Absent leaves a value unchanged; `null` removes the cap. A cap is between $0.000001 and $100,000.

```bash theme={null}
curl -s -X PATCH https://api.zode.dev/v1/billing \
  -H "Authorization: Bearer $ZODE_TOKEN" -H "Content-Type: application/json" \
  -d '{"daily_cap_micros": 5000000, "sandbox_default_cap_micros": 1000000}'
```

* **`sandbox_default_cap_micros`** becomes the `max_cost_micros` of every new sandbox that names none.
* **`daily_cap_micros`** applies per UTC day, in two places:
  * Once today's billed spend (compute and storage) reaches it, creating, forking and starting sandboxes answer 409 `daily_cap_reached`: "today's spend $X has reached the workspace's daily cap $Y; raise it in Billing or wait for 00:00 UTC". Running sandboxes are not stopped.
  * Once today's AI spend through Zode keys reaches it, the host refuses AI calls with HTTP 402 `zode_spend_cap` until 00:00 UTC, and sends `spend.daily_cap_reached`.

`GET /v1/billing` returns the caps with today's spend so far (`caps.today_micros`), this month's usage per meter, the invoice estimate and the credit balance. The same two caps appear in `/v1/proxying` as `caps.daily_cap_micros` and `caps.sandbox_max_cost_micros`; both routes edit the same values.

> [!NOTE]
>
> AI spend for the caps is counted in the host's memory. A host restart starts the count again from zero.

## Read usage

`zode cost` reads the same numbers as the console's Usage page:

```bash theme={null}
$ zode cost
2026-11-05 to 2026-11-11 UTC, as of 2026-11-11 11:04

billed      $0.005875   compute $0.003179   storage $0.002696
AI          $0.000000 in 0 calls, shown, not billed
sandboxes   0.182 h, peak 2 at once, 6 forks (p95 17876 ms)
events      0 OOM kills, 0 breaker trips

REPO     BILLED      AI          HOURS
(none)   $0.005875   $0.000000   0.182
```

Group with `--by repo|branch|pr|member|sandbox|model`, pick days with `--days N` or `--from YYYY-MM-DD --to YYYY-MM-DD`, and add `--csv` for one row per day and group. The default range is the last 7 UTC days, today included.

Repo, branch and PR come from what you set on the sandbox (`git_repo`, `git_branch`, `pr_number`; `zode new --repo --branch --pr`). Usage with none of them lands in the `(none)` group, so totals always add up. `model` groups AI spend as `provider/model`; compute and storage sit in the empty group.

The API behind it:

* `GET /v1/usage?from=YYYY-MM-DD&to=YYYY-MM-DD&group_by=branch`: UTC days, inclusive, at most 92 (default the last 30). Returns `totals`, a `series` entry per day, `groups` (most expensive first) and `ai_by_model`.
* `GET /v1/usage.csv` with the same parameters: columns `day, <group_by>, sandbox_hours, compute_micros, storage_micros, static_ip_micros, billable_micros, ai_micros_not_billed, ai_calls`.

Totals, the daily series, the groups and the CSV rows always sum to the same amounts. Every role can read usage.

> [!NOTE]
>
> AI figures come from the flight recorder, which the hosts do not write to yet, so AI spend currently reads \$0.


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