Skip to main content
Approvals put a human in the loop before an agent does anything high-stakes. When an agent triggers a sensitive action, the API freezes the request and returns 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

naive approvals list --status pending
naive approvals approve <approval-id>
naive approvals deny <approval-id> --reason "not authorized"

Tools

ToolTypeDescription
approvals_listCoreList approvals (filter by status)
approvals_getCoreFetch a single approval + its result/error
approvals_approveCoreApprove → API replays the frozen action
approvals_denyCoreDeny with an optional reason

What’s gated by default

Actionaction_type
Issue a virtual cardcards.create
Create a cardholdercards.cardholder.create
Top up a cardcards.topup
Purchase a domaindomains.purchase
Start KYC (verification)verification.start
Form a companyformation.create
File the formationformation.submit
Connect / sign up for a 3rd-party serviceconnections.connect
Operators override this per primitive in the Account Kit (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

import { isPendingApproval } from "@usenaive-sdk/node";
const alice = naive.forUser("alice");

// 1. Agent attempts a gated action → pending, not executed
const res = await alice.cards.create({ name: "Ads", spendingLimitCents: 50000 });
if (isPendingApproval(res)) {
  // res.approval_id — surface it to the human who can approve
}

// 2. A human approves → API replays the action
await alice.approvals.approve(res.approval_id);

// 3. Inspect the outcome
const a = await alice.approvals.get(res.approval_id); // status: "executed" + result
Pending response (202):
{
  "status": "pending_approval",
  "approval_id": "65589c8b-e033-4a65-b16c-379211c94429",
  "action_type": "cards.create",
  "primitive": "cards",
  "title": "Issue virtual card \"Ads\""
}
A pending approval becomes executed (with the action’s result), failed (with an error), or denied.

Error Handling

ErrorCauseRecovery
not_foundInvalid approval_id / user_idUse GET .../approvals?status=pending
invalid_inputApproval already resolved (executed/denied)Fetch it to see the terminal status
forbiddenCaller may not resolve this approvalApprove as the operator (session or workspace key)

Typical Workflow

Agent tries to issue a card for Alice (gated by her Account Kit)

    ├─ POST /v1/users/alice/cards                  → 202 pending_approval, approval_id

    ├─ (your app shows Alice/operator the pending action)

    ├─ POST /v1/users/alice/approvals/{id}/approve → API replays cards.create
    │   → status: executed, result: { card_id, checkout_url }

    └─ GET  /v1/users/alice/approvals/{id}         → confirm executed + inspect result