Skip to content

Approvals

A payment needs a human when it crosses requireApprovalAbove, exceeds a budget with onBudgetExceeded: approve, is a large first payment to a new recipient, or jumps in price.

Hold mode (default). The agent’s request stays open until someone decides or approvals.timeout passes (then it’s denied). Good for CLIs and scripts.

Retry mode (hold: false). spendctl answers 402 immediately with "error": "spendctl_approval_required" and an approval id. After approval, the agent retries with X-Spendctl-Approval: <id>. An approval pays for exactly one retry.

Terminal window
spendctl pending
spendctl approve apr_… # or --latest / --all
spendctl deny apr_… --note "use the cached result"
  • Dashboard: spendctl dashboard --open.
  • Webhooks: format: json | slack | discord. Payloads include the reason, the CLI command and a review link. Set secretEnv to sign payloads (X-Spendctl-Signature: sha256=…).
  • Review link: HMAC-bound to the admin token. Opening it (GET) only shows the request — chat apps prefetch links — and the Approve/Deny buttons POST.

Agents cannot approve: every decision needs the admin token in .spendctl/admin.token (mode 0600).