Wallet
A non-custodial Tempo balance — deposits, sends and conversions. Nothing on this surface can sign; the holder's own passkey is the only signer, on their own device.
Mixed status by resource
Reads (wallets, balances, transactions) are available today. Everything that prepares a money movement (deposit_intents, send_intents, offramp_intents, conversions) is dark-flag — live behind a cohort, answering capability_unavailable until it opens for a given account. Read the reference for each operation's own status rather than assuming from this page.
Concept
The wallet is the holder's own Tempo balance. The API can read it, price a deposit or a send, and build the unsigned steps for one. It holds no wallet key, so it cannot sign a send for you, and it cannot recover the wallet if no usable passkey or synced copy remains. Provider and token restrictions may still apply.
Resources
| Object | What it is |
|---|---|
wallets / balances / transactions | The holder's address, per-stablecoin balances plus a computed USD total, and a bounded recent-activity window. |
virtual_accounts | Bank details the holder can receive a transfer into. What arrives is delivered to the wallet as stablecoin. See Receive by bank. |
deposit_intents | A one-time, amount-bound cross-chain deposit address — single-use, expires. |
send_intents | A prepared cross-chain withdrawal — the ordered steps the holder's passkey signs, quoted net of fees. |
offramp_intents / external_accounts | A prepared payout to the holder's own verified bank account — never a third party's, on anyone's behalf. |
conversions | An unsigned on-chain swap transaction, built but never sent by the API. |
Minimal flow (a cross-chain send)
GET /v1/wallet/balances— or the MCP toolget_wallet_balance.POST /v1/wallet/send_intents— prepare the withdrawal (prepare_wallet_withdrawal); nothing leaves the wallet yet.- The holder reviews the quoted amount and signs the returned steps with their own passkey.
POST /v1/wallet/send_intents/{id}/source_tx— record the broadcast hash (confirm_wallet_withdrawal) so settlement can be tracked.GET /v1/wallet/send_intents/{id}— orget_transfer_status— to watch it settle.
Receive by bank
A virtual account gives the holder bank details to receive a transfer into. GET /v1/wallet/virtual_accounts lists them and POST /v1/wallet/virtual_accounts creates one. Two fields say what kind of account a row is:
destination.railis the bank rail:ach,sepa,spei,faster_payments,pix,wireorbre_b. It has one spelling per rail: an account the provider sync recorded asach_pushis published asach, as an account created through/v1always was. It is an open enum, so a client tolerates a rail it does not know, and a stored rail outside the list is published as stored.provider_environmentissandbox,productionornull.sandboxmeans a provider test account: its bank details are test data and no real bank transfer arrives.nullmeans no environment was recorded and is never evidence that an account is live. Onlysandboxmarks a test account. Swaps does not work it out from the host or fromlivemode, which stays the caller's own mode.
Not every currency can be opened. When a Payment links collection account already receives a currency into the same wallet, GET /v1/capabilities?product=wallet_bank reads that corridor not_enabled with blocked_reason: collection_account_uses_currency and action: none, and POST /v1/wallet/virtual_accounts for it answers 409 conflict. Read the capability before offering the account. See Providers and coverage.
Where a transfer came from
Each transfer in GET /v1/wallet/transactions (and GET /v1/wallet/transactions/{hash}, or the MCP tool list_wallet_activity) carries origin. On the list every row has it: null, or an object.
origin | Meaning |
|---|---|
{ "kind": "bank_deposit", "virtual_account_id": "va_…", "currency", "rail" } | An incoming transfer that one of the caller's own wallet virtual accounts recorded as the delivery of a bank deposit. currency and rail are that account's destination.currency and destination.rail, spelled the same. The deposit is still one transfer row. |
null | Any other transfer, and any transfer Swaps cannot tie to one account: a hash claimed by two accounts, an account you may not read, or an events lookup that failed. null is not proof that a transfer is not a bank deposit. |
Only an owner or admin who may read the account sees bank_deposit; a business key or another member reads null. It is never inferred from the sender, the amount or the timing, and it never carries a provider id or a bank account number. kind and rail are open enums; tolerate a value you do not know. On the single read, a missing origin means the same as null.
Degraded means unknown, never zero
A rate-limited chain read returns degraded: true with an empty list — never read that as "no activity" or a zero balance. History here is a bounded recent window, not a full ledger.
What an agent can and cannot do here
Every wallet-write tool prepares — prepare_wallet_withdrawal, create_deposit_address, prepare_bank_withdrawal — and returns unsigned steps or a deposit address; none of them broadcasts anything. Adding a bank destination is own-account only and re-verified against the provider at spend time — an agent can never add one on someone else's behalf.
Next: the reference for the full intent schemas · Pay an invoice for the fiat-out counterpart that doesn't touch the wallet.