OXYGENOxygen/ Docs
Safety & cost

Spend caps

A per-run credit limit. Work past the limit is skipped, not charged.

A spend cap is the maximum number of credits one run can consume. It is required on every live table, enrichment, or workflow run that touches a paid provider.

Setting a cap

Preview first — it costs nothing — then re-run with the cap:

oxygen columns run <table-id> <column-key> --dry-run --json
oxygen columns run <table-id> <column-key> --background --limit 50 --approved --max-credits 50 --json

oxygen table-runs create <table-id> --column <column-key> --limit 100 --approved --max-credits 100 --json

oxygen enrich-column preview <table-id> --capability work_email --limit 100 --json
oxygen enrich-column run <table-id> --capability work_email --limit 100 --approved --max-credits 100 --json

oxygen workflows call <workflow> --input-json '{...}' --mode dry_run --json
oxygen workflows call <workflow> --input-json '{...}' --mode live --approved --max-credits 100 --json

The 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

The run does not pause and it does not fail. Items still pending when the reservation reaches the cap are marked skipped with skippedReason: "credit_limit_reached", and the run then finalizes as completed (or completed_with_errors if unrelated items failed). Items that already succeeded keep their results and their captured cost.

oxygen table-runs items <run-id> --status skipped --json | jq '.data.items[].skippedReason'

Because a capped run terminates rather than parks, table-runs resume will not continue it — that command only resumes a run you paused yourself with table-runs pause. To process the remaining rows, create a new scoped run with a new --max-credits value.

oxygen table-runs pause <run-id> --json
oxygen table-runs resume <run-id> --json
oxygen table-runs cancel <run-id> --json

When you do not set one

An autonomous trigger — a workflow cron, webhook, or event, or a table auto-run — armed without an explicit --max-credits resolves a default per-delivery ceiling from your plan tier at fire time. An explicit cap always wins. The per-tier numbers are in the pricing reference.

How binding that default is depends on the trigger:

TriggerDefault ceiling without --max-credits
Table auto-run (import, insert, upsert, webhook-written rows)Binding. Rows past the ceiling are skipped with credit_limit_reached, and a delivery that cannot resolve the ceiling is not enqueued at all
Workflow cron, webhook, or eventMonitored, not binding. The ceiling is resolved and recorded per delivery, but it does not stop the run

Pass an explicit --max-credits when you arm a workflow trigger. An uncapped autonomous workflow delivery is bounded only by your credit balance and the org-daily guard.

Picking a cap

For a blueprint: preflight, then cap at the forecast plus a small buffer. Only price-aware seeds return pricing_forecast; the rest carry no estimate.

oxygen blueprints preflight <slug> --input-json '{...}' --json \
  | jq '.data.preflight.pricing_forecast | {total_credits, minimum_required_credits, cap_status}'

For batched column runs: rows × per-call cost.

oxygen tables query <table-id> --limit 1 --json | jq '.data.total_count'
oxygen tools get <tool-id> --json | jq '.data.tool.estimated_credits_per_call'

Org-level guardrails

Standing caps above the per-run ceiling are budget policies, one per scope + window:

oxygen budget set --scope org --window daily --max-credits 5000 --action hard_block --json
oxygen budget list --json

--scope is org, table, workflow_trigger, or monitor; --window is per_run, daily, or monthly; --action is hard_block (default) or warn.

Underneath those sit two guards you do not configure: the plan-tier default per-delivery ceiling above, and — only while the org has no explicit org-daily policy of its own — an implicit org-daily guard that warns at 25% and blocks at 100% of your monthly credits spent in one day. Watch the balance with:

oxygen billing balance --json
oxygen billing usage --limit 50 --json

See Billing.

  • Approvals — caps are part of the approval card.
  • Modes — only live runs require caps.
  • Runs — inspecting run status and item outcomes.

On this page