Skip to main content
The company wallet flips the default user funded model: your organization prefunds one pooled wallet, and when a connected user’s agent creates a card, Agentcard moves exactly that card’s amount from your pool into the user’s spending power. Your users never see a funding step, and you stay in the transaction loop to collect from your own customer first.
The flow of funds is chosen once, when you create the organization (user funded or company wallet) and cannot be changed later. Company-wallet orgs get the full sandbox loop immediately and free; live usage (the real pool, real transfers) requires an active paid subscription, the same one that unlocks production clients. Want to switch models? Create a new organization and pick the other flow.

The flow of funds

Company wallet flow of funds diagram
Step by step, for one card:
  1. A connected user’s agent calls create_card with the company flow. Agentcard checks your pool covers the amount (plus fees) and reserves it.
  2. You receive a card_flow.started webhook. This is your moment to collect: place a hold on your customer’s payment method in your own billing system.
  3. You report the outcome with the confirm_collection tool — outcome succeeded, or failed to release the reservation.
  4. Agentcard transfers the amount from your wallet into the user’s spending power (about 30 seconds on-chain) and emits transfer.initiated, then transfer.completed.
  5. Capture your customer’s payment when you receive transfer.completed. From this point the funding is final: even if the card mint failed afterward, the money stays as that user’s spending power and automatically offsets their next card (you would see card_flow.failed with funds_status: released_to_headroom).
  6. The card mints and card.created fires with the transfer_id, then the agent pays the merchant as usual.
  7. If the card closes with unused balance, transfer.released fires so you can release or refund your own hold. The unused amount stays as that user’s spending power and reduces what your pool sends on their next card.
Orgs that prefer not to confirm each funding can set ack_mode: auto_approve (dashboard or CLI): step 2 still fires as a webhook, but the transfer proceeds without waiting.

Fund the wallet

Provision the wallet once (dashboard: Company wallet → Create company wallet, or agent-cards-admin wallet provision --org <org-id>), then send USDC on Base to its deposit address. Deposits are detected automatically and confirmed with a wallet.funded webhook. Set a low-balance threshold to get wallet.balance.low before a card creation ever fails for insufficient funds. Creating the live pool and running live transfers both require the active subscription; without one these calls return 403 subscription_required (sandbox credentials and the mock pool keep working). Subscribe from the dashboard’s Go live page.

The create_card protocol

The end user’s agent calls the same create_card it always has. Two additions:
  • An optional funds_source (onramp_flow or company_flow). Most orgs set their default funds source to company_flow so agents never pass it.
  • While funding is in flight, create_card returns 202 { "status": "funding_in_progress", "transferId": "owt_…", "retry_after_seconds": 10 }. The agent retries with the same arguments and attaches to the in-flight funding, returning the card when it is ready. A retry that lands after the mint still returns that card (for about 2 minutes, while it is unused) instead of opening a second funding. Declined or timed-out collections surface as 422 funding_not_approved.
Server-initiated issuance works too: your backend can call create_card itself with funds_source: "company_flow". Your own call counts as the collection confirmation, and passing an idempotency_key makes retries attach instead of double-funding. Reusing a key with a different amount or cardholder is rejected with 409 idempotency_key_reuse; use a fresh key for each new request.

Wallet tools

Available with your org credentials:
ActionTool
Balances, deposit address, settingsget_company_wallet
List transfers (filter by status)list_transfers
Confirm or fail your collectionconfirm_collection
Flow settings (ack_mode, thresholds)Dashboard → Company wallet, or the admin CLI
Add sandbox test fundsDashboard → Company wallet (sandbox mode)
Transfers move through public states pending (substates: awaiting_collection, collection_confirmed, transferring), funded, consumed, reclaimed, and failed (with a failure_reason).

Test it in sandbox

The whole loop runs in test mode with no real money: fund the mock pool from the dashboard’s Company wallet page (sandbox mode), then run create_card with a sandbox credential. The same webhooks fire with livemode: false, the transfer simulates in about 2 seconds, and the card is a mock. Integrate the webhook and collection confirmation exactly as you would in production.

Events

EventFires whenWhat you do
card_flow.startedA user’s card creation reserved your poolHold your customer’s payment method, then confirm collection
transfer.approvedCollection confirmed (by you or auto-approve)Nothing, informational
transfer.initiatedThe on-chain transfer was submittedNothing, informational
transfer.completedFunds are the user’s spending powerCapture your customer’s payment
card.createdThe card minted (includes transfer_id)Final confirmation
transfer.failedFunding aborted before the card (insufficient_org_funds, ack_timeout, ack_denied, transfer_failed)Release your hold
card_flow.failedMint failed after funds moved (funds_status: released_to_headroom)Keep your capture, the user keeps the spending power
transfer.releasedCard closed or expired with unused balanceRelease or refund your own hold
wallet.fundedA deposit landed in your poolReconcile your treasury
wallet.balance.lowThe pool dropped under your thresholdTop up