Spend caps
A per-run credit limit. The run pauses when the cap is hit.
A spend cap is the maximum number of credits one run can consume. It is required on live table, enrichment, company enrichment, and workflow-template runs that touch paid providers.
Setting a cap
oxygen columns run <table-id> <column-key> --background --limit 50 --max-credits 50 --json
oxygen table-runs create <table-id> --column <column-key> --limit 100 --max-credits 100 --json
oxygen enrich-column run <table-id> --capability work_email --limit 100 --max-credits 100 --json
oxygen workflows templates run <template-id> --input-json '{...}' --mode live --max-credits 100 --approved --jsonThe cap applies to the whole run, not per item. A run with 500 items and a 50-credit cap can process at most 50 items if each costs 1 credit.
What happens when a cap is hit
| State | Behavior |
|---|---|
succeeded items | Stay completed; their cost is captured |
running item | Allowed to finish, then the run pauses |
pending items | Stay pending; run pauses |
| Reservation | Frozen at the cap |
oxygen runs get <run-id> --json
# .data.status == "paused"
# .data.pause_reason == "cap_reached"Continuing or stopping
oxygen table-runs resume <run-id> --json
oxygen table-runs cancel <run-id> --jsonIf a cap stops a paid run and you want to process more rows, create a new scoped run for the remaining rows with a new --max-credits value.
Picking a cap
For new workflows: preflight to get the estimate, then cap at the estimate plus a small buffer.
oxygen workflows templates preflight <id> --input-json '{...}' --mode dry_run --json
# .data.credits.estimated_max -> use this + 10-20% as the capFor batched column runs: count rows × per-call cost.
oxygen tables describe <table-id> --json | jq '.row_count'
oxygen tools get <tool-id> --json | jq '.estimated_credits_per_call'Org-level guardrails
There's no global per-org spend cap (yet). Caps are per-run only. Watch the balance with:
oxygen billing balance --json
oxygen billing usage --limit 50 --jsonSee Billing.