Skip to main content
Moves a balance from one of your users’ addresses to another user’s address on your account. Use it when your users settle with each other, split a bill, or pay one another inside your product.
Backend only. Never call from frontend.
A transfer is an ordinary on-chain send between two addresses you created, made on your API instruction. Because the receiving address is provably yours, it doesn’t need to be on your approved destinations list the way a withdrawal does.

Endpoint

Requires the transfer scope. It defaults off on every key, including keys created before scopes existed. Contact us to turn it on for a key that should be able to move money between your users.

Body

string
required
The walletRef of the user paying.
string
required
The walletRef of the user being paid. Must be a different address from from.
string
required
The chain to send on. Both addresses need to be live on it. Transfers stay on one chain; to consolidate balances across chains, use settlement.
string
required
USDC or USDT.
number
required
A positive number, in the token’s units, with at most 6 decimal places. The smallest transfer is 0.1 on most chains, 0.5 on Avalanche and 20 on Ethereum.
string
Reusing the same key with the same request returns the original transfer instead of sending a second one. Reusing it with a different from, to, chain, token or amount is refused with 409. Keys are shared with withdrawals, so a key you used for a withdrawal can’t be reused for a transfer.

Example

Response (202)

202 means the transfer is accepted and queued, and it goes out shortly after. Poll get a transfer or listen for wallet.transfer.completed. Replaying an idempotency_key returns 200 with the original transfer.
string
required
queued, sending, completed, failed, or under_review. failed means nothing moved and the amount is still at the from address. under_review is rare: we couldn’t confirm the outcome, so we’re checking it. Don’t treat it as either paid or failed yet.
string
The on-chain transaction, once it completes. null until then, and while failed.
The receiving address does not get a wallet.deposit.received for a transfer. Credit the receiver in your own records from wallet.transfer.completed, so the same money is never counted twice.

Errors

Listing your transfers

Needs wallets:read. Newest first.
number
default:"20"
Page size, max 100.
number
default:"0"
Rows to skip.

Getting one transfer

Needs wallets:read. Returns { "transfer": { ... } } in the same shape as above, or 404 for an id that isn’t yours.