Quickstart
A full round-trip against staging with curl. Replace the key with your own.
BASE=https://api-staging.zenvault.io/api
KEY="zv_a1b2c3d4_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1. Create a vault
A web3 vault is a single MPC-EOA that holds ETH and every ERC-20 at one
address — the right choice for EVM assets.
curl -s -X POST "$BASE/v1/accounts" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"label":"demo-1","purpose":"hot","vaultType":"web3","firstAssetCanonical":"USDT_ETHEREUM"}'
The response includes the account id and echoes the chosen type as
tags.vaultType.
2. Generate a deposit address
curl -s -X POST "$BASE/v1/accounts/<ACCOUNT_ID>/addresses" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"assetCanonical":"USDT_ETHEREUM"}'
Give the returned address (and memo, if present) to the payer. On
confirmation you receive an address.received webhook.
3. Read a balance
curl -s "$BASE/v1/accounts/<ACCOUNT_ID>/balances/USDT_ETHEREUM" \
-H "Authorization: Bearer $KEY"
Balances are read live from custody at request time.
4. Send a withdrawal (idempotent)
curl -s -X POST "$BASE/v1/transfers/external" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"srcAccountId":"<ACCOUNT_ID>","assetCanonical":"USDT_ETHEREUM","amount":"10.00","destination":{"address":"0xfeed...beef"}}'
The response is a transfer in signing — track it to completed (or failed)
via webhooks. Always send an Idempotency-Key so a retry can't
create a duplicate.
tip
Depending on your workspace's policy, a
withdrawal may come back in state held (awaiting approval) or be rejected with
403. Handle both.
Next
- Receive a deposit — the full deposit flow.
- Send a withdrawal — allowlisting and tracking.
- API conventions — pagination, idempotency, errors.