Skip to main content
A sub account is named by its acc_… id in the fields that take an account key of your main wallet. Send the id as sourceAccount on POST /dapi/v1/payouts to pay a contact from it. The examples bind me to your own cl_… id, as in the Quickstart. For a session that acts for a client, the signed routes return 403 account_not_controlled.

Payouts

Call POST /dapi/v1/payouts with the contact, the amount, the sub account as sourceAccount and your publicKey.
Response 201, Location: /dapi/v1/payouts/po_7e1b…
Check debit, sign approval.payload and call POST /dapi/v1/payouts/{payoutId}/confirm, as for a payout from your main wallet (Signing). Fields: Create an outgoing transfer. debit.sourceAddress is the address of the sub account, and the amount is in the token it holds. The other debit fields and the checks to run before you sign are in Debit contents. Statuses and the other refusals are in Payouts.

Moves

A move is a swap with a sub account on either side: one token, one for one, no fee. Call POST /dapi/v1/swaps with an account key or an acc_… id on each side. POST /dapi/v1/swaps/preview takes the same accounts and has no side effects.
The response has authorization: "debit" for the account the money leaves. debit.sourceAddress is that account’s address and debit.address is the address of the receiving account. Sign and confirm with POST /dapi/v1/swaps/{swapId}/confirm, then read GET /dapi/v1/swaps/{swapId}, which returns both account ids (Swaps).

Other tokens

A token the sub account does not hold, for example EURC, can still be sent to its address. That token is not in balance, and it cannot pay a payout or move to another sub account. To move it out, call POST /dapi/v1/swaps with the sub account as sourceAccount and the account key of that token as destinationAccount. The token goes to your main wallet one for one, with no fee and no conversion, under authorization: "debit".
No balance route reports the amount of such a token. Read it from the ledger row of the incoming transfer.

Payins

Call POST /dapi/v1/payins with the sub account as destinationAccount and originChainId. The payer sends an on-chain transfer, and the sub account receives the token it holds at its address on Base.
The payin has accountId set to the sub account. Open it with POST /dapi/v1/payins/{payinId}/instructions as for your main wallet (Payins). Fields: Create an incoming transfer quote.

Virtual accounts

Call POST /dapi/v1/banks with product and accountId to request a virtual account that delivers to the sub account (Quickstart). Each sub account has its own record per product, with its own account details, returned as requisites. A product is accepted when its rail delivers the token of the sub account on chain to an address (Deliver to an account). Statuses, blockers and account details are in Virtual accounts.

Balance and ledger

Income of a sub account counts in the unfiltered summary of your account. A move writes two rows of type: "move", one per account, and both are left out of unfiltered totals. A transfer that arrives from outside HEVN appears after a ledger refresh, which POST /dapi/v1/transactions/sync runs (Refresh the ledger).

RD sub accounts

A sub account opened with asset: "RD" follows the rules above with RD in place of USDC.

Sandbox

In the sandbox a sub account holds USDC, and you fund it through a virtual account or the faucet. The differences from production, with the products, limits and refusals, are in Accounts.

Next: Signing