Usage & Billing
Pooled credit at the org, usage metered per customer workspace.
Billing for an embedded fleet follows one rule: credit is pooled, usage is attributed. Your org pays from one balance; every workspace reports its own share of the spend, so you always know what the feature costs to run per customer.
One pool
Plan, allowance, and prepaid balance live on the org's primary workspace and cover the whole org. A customer workspace never needs its own top-up, and there's no per-workspace balance to babysit — a run in any workspace draws from the shared pool. Manage the plan and top-ups from the primary workspace's Settings → Billing, like any other workspace; see Plans & Billing for how credits work.
When the pool runs out, runs are gated across the org until it's topped up. Suspending a workspace is never about billing — it's your lifecycle switch for offboarded customers.
Per-customer attribution
GET /api/v1/org/usage returns
the pooled balance and month-to-date spend, broken down by workspace:
{
"tier": "enterprise",
"balance_usd_micros": 412500000,
"current_month_spend_usd_micros": 87500000,
"workspaces": [
{
"id": "…",
"name": "Acme Tools",
"headless": true,
"lifecycle": "active",
"current_month_spend_usd_micros": 61250000
}
]
}Amounts are in millionths of a USD (61250000 = $61.25). This is the number to
feed your own pricing: meter it, margin it, or bundle it — the per-customer cost
is yours to see either way.
Export to your billing system
GET /api/v1/org/usage/export
returns the same spend as line items a billing system ingests — one per
workspace and meter, for any period you name (start inclusive, end
exclusive, UTC days):
GET /api/v1/org/usage/export?start=2026-08-01&end=2026-09-01{
"period_start": "2026-08-01",
"period_end": "2026-09-01",
"total_usd_micros": 87500000,
"line_items": [
{
"workspace_id": "…",
"period_start": "2026-08-01",
"period_end": "2026-09-01",
"meter": "llm.daily",
"unit": "request",
"quantity": 1240,
"amount_usd_micros": 58250000
},
{
"workspace_id": "…",
"period_start": "2026-08-01",
"period_end": "2026-09-01",
"meter": "sandbox.minute",
"unit": "minute",
"quantity": 361.5,
"amount_usd_micros": 3000000
}
]
}amount_usd_micros is always the billable figure; quantity and unit are
there when your pricing is per-request or per-minute rather than
cost-plus. The export and GET /api/v1/org/usage sum the same rows exactly —
integer micros, no rounding — so for a period equal to the current calendar
month so far, a workspace's line items add up to its
current_month_spend_usd_micros.
Billing a period with Stripe
The line items map onto Stripe's metered billing directly:
- Report each line item as a billing meter event
for the customer that owns the workspace —
valuefromamount_usd_micros(orquantity, if you price per unit), timestamped at the period's end. - Derive both the meter event's
identifierand the request's idempotency key from(workspace_id, meter, period_start, period_end)— for example"{workspace_id}:{meter}:2026-08-01:2026-09-01".
That tuple is the idempotency rule: a period you have already billed can be re-read and re-sent at any time, and Stripe deduplicates it to the event you already recorded. Two things make this safe:
- Bill closed periods only. The current day's figures are provisional and still growing; a day settles shortly after it closes (UTC). Re-reading a settled period always returns the same line items, so the export is stable by the time you bill it.
- Never reuse a key across periods. The period is part of the identifier, so August's re-run can't swallow September's first send.
The same rule works for any billing system with idempotent ingestion — the export gives you a stable natural key per line item.
Cap a customer
Attribution tells you what a customer costs; a hard spend cap bounds it. Set one per workspace and one customer's busy week stays theirs — the shared pool keeps funding everyone else:
curl -X PUT https://api.levainlabs.com/api/v1/org/workspaces/$WORKSPACE_ID/cap \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "Content-Type: application/json" \
-d '{"hard_cap_usd_micros": 25000000}'The cap is a ceiling on that workspace's own month-to-date spend. Read it back
(with the spend it counts against) via GET /api/v1/org/workspaces/{workspace_id}/cap; send null to remove it, 0 to
refuse every new run.
At the cap, the behavior is:
- A run that would cross the cap is refused before it starts, with reason
workspace_cap_hit. A run already in progress completes, so spend can overshoot the cap by at most one turn. - A
workspace.cap_reachedevent is delivered to your webhook endpoints, once per workspace per month, with the cap and the spend that hit it. - Scheduled runs pause instead of failing on every tick.
The block — and the paused schedules — lift when the month rolls over or you raise or remove the cap. The cap never touches the org's pooled balance: it's a per-customer budget, not a payment boundary. For offboarding, use the lifecycle switch instead.
Finer grain
For finer grain — per agent, per run, per day — the
Analytics endpoints work per workspace like everything else:
send X-Workspace-Id with an org key and you get that customer's breakdown.