Fund the wallet
Three ways in, one balance. A top-up by card or stablecoin ends on Stripe's own page, a bank transfer is declared and matched when it lands, and a new account starts with a small gift. A card number never passes through the API.
Read the wallet
curl https://api.joomjoo.com/v1/wallet \
-H "Authorization: Bearer $AGENTPAY_API_KEY"{
"currency": "USD",
"onboarded": true,
"balance": 32.96,
"available": 22.96,
"reserved": 10,
"pending": 0,
"balance_display": "$32.96",
"available_display": "$22.96",
"reserved_display": "$10.00",
"pending_display": "$0.00",
"cards_ready": [{ "last4": "8339", "network": "visa", "holds": 10 }],
"ready_to_spend": 32.96,
"charges_in_flight": [],
"after_settlement": 32.96,
"note": "A checkout whose total fits one of the 1 card(s) in cards_ready pays with it, no new card and no top-up needed. Call complete_purchase.",
"request_id": "req_a1b2c3"
}available is what a new card can be capped at. cards_ready lists open, never-charged single-use cards: a checkout whose total fits one of them pays with it, so ready_to_spend is the honest number for "can the agent buy this". charges_in_flight names authorized charges still settling; the balance becomes after_settlement once they clear. That is normal, not a failed purchase.
Top up by card or stablecoin
POST /v1/wallet/funding-sessions opens a Stripe Checkout page for the amount. Give url to the person. Stripe offers card and stablecoin; the wallet is credited the moment Stripe confirms.
curl https://api.joomjoo.com/v1/wallet/funding-sessions \
-H "Authorization: Bearer $AGENTPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 50, "success_url": "https://yourapp.example/funded"}'const session = await agentpay.wallet.createFundingSession({ amount: 50, success_url: "https://yourapp.example/funded" });
// send session.url to the personsession = agentpay.wallet.create_funding_session(amount=50, success_url="https://yourapp.example/funded"){
"funding_session_id": "cs_live_...",
"url": "https://checkout.stripe.com/c/pay/...",
"amount": 50,
"amount_display": "$50.00",
"status": "open",
"pays_with": "card or stablecoin on the Stripe page",
"credited": "the wallet is credited the moment Stripe confirms; subscribe to money.funded to know",
"request_id": "req_a1b2c3"
}Subscribe to money.funded to know when the money landed, or poll GET /v1/wallet. A fence can refuse an amount: 402 wallet_limit, funding_budget_reached or funding_unavailable, and the message says which.
Never ask the person for a card number and never type one yourself. The top-up always ends on Stripe's page.
Top up by bank transfer
POST /v1/wallet/bank-transfers declares a transfer and returns the account to send it to, with a reference code for the memo. The money is pending until it lands; then money.funded fires and the balance moves.
curl https://api.joomjoo.com/v1/wallet/bank-transfers \
-H "Authorization: Bearer $AGENTPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 500, "rail": "wire_domestic", "sent_on": "2026-11-03", "sender_bank_name": "Chase", "idempotency_key": "topup-2026-11-03"}'rail | Currency | Notes |
|---|---|---|
ach (default) | USD | US domestic. |
wire_domestic | USD | US wire. |
wire_international | USD | SWIFT. The response carries the SWIFT and intermediary codes. |
uae_local | AED | A UAE account. Defaults currency to AED. |
Show the person the instructions object as it is. The reference_code in the transfer memo is what matches the money to the account; without it the transfer waits for a manual match.
The signup gift
A new account's first card is issued at onboarding, single use, loaded with a small gift. It shows up in cards_ready and pays a first checkout whose total fits it. The gift cannot be withdrawn and expires with the card.