Skip to content

Quick Start

End-to-end walkthrough of the core API: create a vault, create a wallet, check the balance, estimate a fee, submit a withdrawal, and track it.

Prerequisites

You need an API Key ID and Secret. Your tenant administrator creates them in the admin dashboard under Settings → API Keys. See Authentication for the HMAC-SHA256 signing algorithm.


Authentication

Every request requires three HMAC signature headers. See Authentication for the full signing algorithm and code examples.

All examples below use $HEADERS as shorthand for:

-H "X-API-Key: $API_KEY_ID" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: $SIGNATURE"

Step 1: Create a Vault

A vault represents your end-customer whose assets will be held in custody.

curl -X POST {{baseUrl}}/vaults \
  $HEADERS \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "cust_12345",
    "name": "Alice Johnson"
  }'

Response (201):

{
  "id": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
  "externalId": "cust_12345",
  "name": "Alice Johnson",
  "metadata": {},
  "status": "Active",
  "createdAt": "2026-02-22T10:00:00Z"
}

Note the vault id -- you will use it when creating wallets.


Step 2: Create a Wallet

Create a wallet for a vault. You need the vault ID from Step 1 and an asset ID (available from the dashboard under Assets).

curl -X POST {{baseUrl}}/vaults/d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890/wallets \
  $HEADERS \
  -H "Content-Type: application/json" \
  -d '{
    "assetId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "label": "Primary ETH Wallet"
  }'

Response (201):

{
  "id": "f4a5b6c7-d8e9-0123-fabc-456789abcdef",
  "vaultId": "d1e2f3a4-b5c6-7890-d1e2-f3a4b5c67890",
  "assetId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
  "assetName": "Ethereum",
  "assetSymbol": "ETH",
  "network": "Ethereum",
  "label": "Primary ETH Wallet",
  "depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
  "depositTag": null,
  "status": "Active",
  "createdAt": "2026-02-22T10:30:00Z"
}

The depositAddress is the on-chain address where this wallet can receive funds. Share this with your end-customers for deposits.


Step 3: Check Wallet Balance

curl {{baseUrl}}/wallets/f4a5b6c7-d8e9-0123-fabc-456789abcdef/balance $HEADERS

Response (200):

{
  "available": "1.5000",
  "pending": "0.2500",
  "locked": "0.0000",
  "total": "1.7500"
}
Field Description
available Balance available for withdrawal or transfer.
pending Incoming deposits not yet confirmed on-chain.
locked Funds reserved by in-flight transactions.
total Sum of available + pending + locked.

Step 4: Estimate Fees

Before submitting a withdrawal, estimate the network fee.

curl -X POST {{baseUrl}}/transactions/estimate-fee \
  $HEADERS \
  -H "Content-Type: application/json" \
  -d '{
    "sourceWalletId": "f4a5b6c7-d8e9-0123-fabc-456789abcdef",
    "destinationAddress": "0xABC1234567890DEF1234567890abcDeF12345678",
    "amount": "0.5000"
  }'

Response (200):

{
  "low": {
    "networkFee": "0.000049051962603",
    "gasPrice": "1.075798425",
    "gasLimit": "21000",
    "feePerByte": null
  },
  "medium": {
    "networkFee": "0.000049051962603",
    "gasPrice": "1.169768470",
    "gasLimit": "21000",
    "feePerByte": null
  },
  "high": {
    "networkFee": "0.000056458147116",
    "gasPrice": "2.369911802",
    "gasLimit": "21000",
    "feePerByte": null
  }
}

Three fee tiers — low, medium, high — let you offer the user a priority/cost trade-off. Each tier carries networkFee (the estimated total in the native asset, the only field you need for display) plus the chain-specific inputs that produced it:

Field When it appears
gasPrice / gasLimit EVM chains (ETH, USDT-ERC20, etc.) — networkFee = gasPrice × gasLimit, denominated in the native asset
feePerByte UTXO chains (BTC) — fee is per-byte of the signed transaction

Pick a tier client-side (most integrations default to medium) and pass feeLevel: "Low" \| "Medium" \| "High" on the withdrawal request below. Omit it and the withdrawal defaults to medium.


Step 5: Create a Withdrawal

Submit a withdrawal to an external address.

Idempotency-Key is required

Every fund-moving request (/transactions/withdraw, /transactions/transfer) requires an Idempotency-Key header. Generate a unique value per logical operation (UUID, ULID, or a stable business identifier — up to 64 chars, [A-Za-z0-9_-]). If your client retries the same request after a network blip, replaying with the same key returns the original response instead of submitting a second withdrawal. Reusing a key with a different request body returns 400 — that's almost always a client bug.

curl -X POST {{baseUrl}}/transactions/withdraw \
  $HEADERS \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "sourceWalletId": "f4a5b6c7-d8e9-0123-fabc-456789abcdef",
    "destinationAddress": "0xABC1234567890DEF1234567890abcDeF12345678",
    "amount": "0.5000",
    "note": "Monthly treasury sweep"
  }'

Response (201):

{
  "id": "b6c7d8e9-f0a1-2345-bcde-6789abcdef01",
  "type": "Withdrawal",
  "status": "Submitted",
  "sourceWalletId": "f4a5b6c7-d8e9-0123-fabc-456789abcdef",
  "assetSymbol": "ETH",
  "network": "Ethereum",
  "amount": "0.5000",
  "note": "Monthly treasury sweep",
  "createdAt": "2026-02-22T11:15:00Z"
}

Step 6: Track the Transaction

Poll the transaction endpoint or set up webhooks for real-time notifications.

curl {{baseUrl}}/transactions/b6c7d8e9-f0a1-2345-bcde-6789abcdef01 $HEADERS

Transaction Status Reference

Status Description
Submitted Request received by the platform.
PendingSignature Awaiting signing by the underlying custody backend.
Broadcasting Signed and submitted to the blockchain network.
Confirming On-chain, waiting for confirmations.
Completed Fully confirmed and settled.
Failed Transaction failed (see failureReason).
Cancelled Transaction was cancelled before execution.

Bonus: Internal Transfers

Transfer funds between two wallets in the same tenant (same asset). The same Idempotency-Key rule applies — see the warning above.

curl -X POST {{baseUrl}}/transactions/transfer \
  $HEADERS \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "sourceWalletId": "f4a5b6c7-d8e9-0123-fabc-456789abcdef",
    "destinationWalletId": "11223344-5566-7788-99aa-bbccddeeff00",
    "amount": "0.2500",
    "note": "Fund user wallet"
  }'

Internal transfers settle instantly with no network fees.


What's Next

  • Set up webhooks -- Receive real-time notifications instead of polling. See the Webhooks guide.
  • Address book -- Save frequently used addresses for convenience. See Address Book.