202 { status: "pending_approval", approval_id } instead of executing. A human (the
operator, or the end-user in your app) approves or denies it; on approval the API
replays the frozen action and records the result.
Gating is configured per primitive on the Account Kit,
and the queue is a first-class resource alongside vault and logs.
CLI First
Tools
| Tool | Type | Description |
|---|---|---|
approvals_list | Core | List approvals (filter by status) |
approvals_get | Core | Fetch a single approval + its result/error |
approvals_approve | Core | Approve → API replays the frozen action |
approvals_deny | Core | Deny with an optional reason |
What’s gated by default
| Action | action_type |
|---|---|
| Issue a virtual card | cards.create |
| Create a cardholder | cards.cardholder.create |
| Top up a card | cards.topup |
| Purchase a domain | domains.purchase |
| Start KYC (verification) | verification.start |
| Form a company | formation.create |
| File the formation | formation.submit |
| Connect / sign up for a 3rd-party service | connections.connect |
primitives_config.<primitive>.requiresApproval, or
connections_config.requiresApproval). Set true to force approval, false to opt out.
Human (dashboard/session) callers bypass the gate, and so do agent calls on the
operator’s own default user — only agent calls on real tenant users are gated.
Lifecycle
pending approval becomes executed (with the action’s result), failed (with an
error), or denied.
Error Handling
| Error | Cause | Recovery |
|---|---|---|
not_found | Invalid approval_id / user_id | Use GET .../approvals?status=pending |
invalid_input | Approval already resolved (executed/denied) | Fetch it to see the terminal status |
forbidden | Caller may not resolve this approval | Approve as the operator (session or workspace key) |