Skip to main content

Move Funds Between Your Accounts

Use this to fund a sub-account from the main account, sweep a sub-account's balance back to the main account, or move funds from one sub-account to another. It's an internal transfer: no PIX and no on-chain transaction, so it completes in seconds.

Before you start​

  • You need the account ID of the destination. For a sub-account, it's the subAccountId returned when you created it (or listed by GET /v2/account/sub-accounts). For the main account, it's the top-level id of GET /v2/account/account-info called without subAccountId.
  • Both accounts must be yours: the main account and its sub-accounts. An account ID from outside your main account is refused.
  • Internal transfers don't count against your monthly limits.
  • The token is the same on both sides: BRLA, USDC, USDT or EURC.

1. Quote​

The account that sends the funds is the one in the request. To send from a sub-account, add subAccountId; to send from the main account, leave it out.

GET /v2/account/quote/fixed-rate?inputCurrency=BRLA&inputPaymentMethod=INTERNAL&inputAmount=10&outputCurrency=BRLA&outputPaymentMethod=INTERNAL&blockchainSendMethod=PERMIT&inputThirdParty=false&outputThirdParty=false

blockchainSendMethod=PERMIT is required even though nothing goes on-chain. Without it the quote returns 400 InvalidFieldError: inputCurrency-inputPaymentMethod:blockchainSendMethod is invalid.

The response (sandbox, trimmed):

{
"quoteToken": "eyJ...",
"inputCurrency": "BRLA",
"inputPaymentMethod": "INTERNAL",
"inputAmount": "10",
"outputCurrency": "BRLA",
"outputPaymentMethod": "INTERNAL",
"outputAmount": "10",
"appliedFees": [
{ "type": "Markup Fee", "amount": "0", "currency": "BRLA" },
{ "type": "In Fee", "amount": "0", "currency": "BRLA" },
{ "type": "Conversion Fee", "amount": "0", "currency": "BRLA" },
{ "type": "Out Fee", "amount": "0", "currency": "BRLA" },
{ "type": "Gas Fee", "amount": "0", "currency": "BRLA" }
],
"feeSettlement": "IMMEDIATE"
}

Check appliedFees in your own quote: fees depend on your contract.

2. Ticket​

Send the quote token and the destination account ID in ticketBlockchainOutput.beneficiaryWalletId. Despite its name, for an internal transfer that field takes an account ID, not a wallet address. If the quote had subAccountId, the ticket needs the same one, as a query parameter.

POST /v2/account/tickets/
{
"quoteToken": "eyJ...",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "DESTINATION_ACCOUNT_ID"
}
}
{
"id": "819ea5fe-63ee-4657-b16d-b037980857a3",
"expiration": "2026-10-25T18:48:49.485459337Z"
}

3. Confirm​

Read the ticket (with the sender's subAccountId, if any) until status is PAID, or wait for the TICKET-COMPLETE webhook:

GET /v2/account/tickets/819ea5fe-63ee-4657-b16d-b037980857a3

In sandbox both directions reached PAID within a few seconds.

Example: sweep a sub-account back to the main account​

GET  /v2/account/quote/fixed-rate?inputCurrency=BRLA&inputPaymentMethod=INTERNAL&inputAmount=10&outputCurrency=BRLA&outputPaymentMethod=INTERNAL&blockchainSendMethod=PERMIT&inputThirdParty=false&outputThirdParty=false&subAccountId=SUB_ACCOUNT_ID
POST /v2/account/tickets/?subAccountId=SUB_ACCOUNT_ID
{
"quoteToken": "eyJ...",
"ticketBlockchainOutput": {
"beneficiaryWalletId": "MAIN_ACCOUNT_ID"
}
}
{
"id": "6e722e7d-4014-4ed3-84cd-bde0e5454286",
"expiration": "2026-10-25T18:49:07.562907141Z"
}

GET /v2/account/tickets/6e722e7d-4014-4ed3-84cd-bde0e5454286?subAccountId=SUB_ACCOUNT_ID then returned status PAID.

Which IDs go where​

From → TosubAccountId (quote and ticket)beneficiaryWalletId
Main → sub-accountnot sentthe sub-account ID
Sub-account → mainthe sub-account IDthe main account ID
Sub-account A → sub-account BA's IDB's ID

Errors you may see​

ErrorCause
400 InvalidFieldError: inputCurrency-inputPaymentMethod:blockchainSendMethod is invalidblockchainSendMethod missing from the quote.
400 InvalidFieldError: ticketBlockchainOutput.beneficiaryWalletId is invalidThe ID isn't your main account or one of its sub-accounts.
400 InvalidFieldError: quoteToken is invalidThe quote and the ticket don't carry the same subAccountId.

More on owners and destinations in Accounts and Sub-accounts.