Skip to main content
Open a sub account in the sandbox, fund it, pay a contact from it and move the rest to your main wallet. Start by logging in with POST /dapi/v1/auth/challenge and POST /dapi/v1/auth/token.

Before you start

  1. Sign up at https://sandbox.gethevn.com and create a developer key.
  2. Save the private key to $HEVN_KEY_PEM with mode 0600.
  3. Set the environment and install the dependencies.
Developer keys, clients and tokens are per environment. The examples read these variables:
The sandbox runs on Base Sepolia with testnet tokens. A payout, escrow or payin is capped at 1, and a faucet credit at 5 to a wallet holding less than 1. The sandbox money routes take 60 calls per account per hour. See Sandbox limits.
The Python, Node and Go tabs use the reference client. me is the client bound to your own cl_… id, which /client/accounts and /client/balance require.

Steps

1

Log in

Run the login code in Sessions. Export accessToken as HEVN_ACCESS_TOKEN and userId as HEVN_USER_ID.
2

Open a sub account

Call POST /dapi/v1/client/accounts with kind: "sub" and a label.
Response 201, Location: /dapi/v1/client/accounts/acc_9f2c…
A repeat with the same label returns 200 and the same sub account (Label). Fields: Add an account.
3

Request its virtual account

Call POST /dapi/v1/banks with the product and the accountId.
Response 201, Location: /dapi/v1/banks/us?accountId=acc_9f2c…
While status is preparing, blockers[] lists what is pending (What still blocks it). The sandbox accepts us and swift for a sub account. Fields: Request a receiving account for a product.
4

Fund the sub account

Call POST /dapi/v1/sandbox/deposits with the accountId and no bankId. The faucet sends the token the sub account holds to its address.
Response 200
On 202, repeat the same request until status is settled. To emulate a bank transfer to an active virtual account, send {"amount":"1.00","bankId":"bnk_88Hq3T"} and omit accountId. Fields: Emulate an incoming deposit.
5

Read the balance

Call GET /dapi/v1/client/balance. The entry with your accountId is the sub account.
Response 200
The balance of a sub account is read from the network when the last read is older than a minute. Fields: Read a client’s balances.
6

Book a payout from it

Save a USDC contact on Base with POST /dapi/v1/contacts, then call POST /dapi/v1/payouts with the sub account as sourceAccount. Use a Base Sepolia address you hold.
Response 201, Location: /dapi/v1/payouts/po_7e1b…
Fields: Create an outgoing transfer.
7

Check, sign and confirm

Compare debit with the payout you booked, sign approval.payload and call POST /dapi/v1/payouts/{payoutId}/confirm within 120 seconds.
Response 200
debit.sourceAddress is the address of the sub account, and debit.operation is the operation the signature approves (Payouts). Confirm outcomes are in Retrying a confirm.
8

Move the rest to your main wallet

Call POST /dapi/v1/swaps with the sub account as sourceAccount and the account key USDC as destinationAccount. Sign and confirm with POST /dapi/v1/swaps/{swapId}/confirm, then read the swap until it settles.
Response 201, Location: /dapi/v1/swaps/swp_9f2c1ab84d
In cURL, sign approval.payload as in the previous step. Fields: Create a transfer between the client’s own accounts.

Next: Money movement