English
Quickstart
This sequence verifies the core Wallet API integration. First install Node.js, curl, openssl, and jq, then configure the issued integration values as environment variables.
bash
export WALLET_BASE_URL='https://{environment-api-host}'
export WALLET_API_KEY='{issued-api-key}'
export WALLET_HMAC_KEY='{issued-hmac-key}'wallet_request
wallet_request is a shell function defined to call the Wallet API. Its call format is wallet_request <HTTP method> <path and query without the Base URL> [JSON body]. Run the entire code block below in the shell where you configured the environment variables. Configure those variables and register the function again when opening a new shell.
It creates a fresh timestamp and nonce for every request and signs the exact path and body sent over HTTP with HMAC-SHA256.
bash
wallet_request() {
local method="$1"
local request_path="$2"
local body="${3-}"
local timestamp nonce signature
timestamp="$(node -e 'process.stdout.write(String(Date.now()))')"
nonce="$(node -e 'process.stdout.write(require("crypto").randomUUID())')"
signature="$(printf '%s\n\n%s\n\n%s\n\n%s\n\n%s' \
"$method" "$request_path" "$timestamp" "$nonce" "$body" \
| openssl dgst -sha256 -hmac "$WALLET_HMAC_KEY" -binary \
| openssl base64 -A)"
if [ -n "$body" ]; then
curl -sS -X "$method" "$WALLET_BASE_URL$request_path" \
-H "X-API-KEY: $WALLET_API_KEY" \
-H "X-TIMESTAMP: $timestamp" \
-H "X-NONCE: $nonce" \
-H "X-SIGNATURE: $signature" \
-H 'Content-Type: application/json' \
--data-raw "$body"
else
curl -sS -X "$method" "$WALLET_BASE_URL$request_path" \
-H "X-API-KEY: $WALLET_API_KEY" \
-H "X-TIMESTAMP: $timestamp" \
-H "X-NONCE: $nonce" \
-H "X-SIGNATURE: $signature"
fi
}This helper is intended for running the quickstart. Production code should add timeouts, response validation, and a bounded retry policy. See HMAC request signing for the complete signing rules.
1. Discover reference data
This example uses the Ethereum Sepolia testnet. See Supported Networks for mainnet/testnet classification and the network catalog.
bash
usdt_response="$(wallet_request GET '/asset-types?code=USDT&page=1&page_size=20')"
sepolia_response="$(wallet_request GET '/networks?is_active=true&page=1&page_size=100')"
printf '%s\n' "$usdt_response" | jq
printf '%s\n' "$sepolia_response" | jq
export ASSET_TYPE_ID="$(printf '%s' "$usdt_response" | jq -er '.data.items[0].id // empty')"
export NETWORK_ID="$(printf '%s' "$sepolia_response" | jq -er '.data.items[] | select(.chain_id == 11155111) | .network_id')"
wallet_request GET "/assets/by-type-network?asset_type_id=$ASSET_TYPE_ID&network_id=$NETWORK_ID" | jqConfirm success: true, the USDT asset, and the Ethereum Sepolia network. Identify Sepolia by chain_id: 11155111. If it is absent, check subsequent pages and availability in the target environment, then stop until resolved. The asset/network combination must also have data.is_active: true.
Stop before the next request if any response fails or an ID is empty. The example's curl -sS can print JSON even for HTTP errors; | jq only formats the response. Check both the HTTP status and success, and never use null as an ID.
2. Create or reuse a customer account
Look up /users/{uid}/accounts first because POST /accounts is not idempotent. Create a USER account only when the intended account does not exist, then persist its account_id.
bash
export CUSTOMER_UID='user-tutorial-001'
wallet_request GET "/users/$CUSTOMER_UID/accounts" | jqIf the intended active USER account exists, set its returned account_id and skip creation. When several accounts exist, select one using your persisted customer mapping.
bash
export ACCOUNT_ID='{existing-active-user-account-id}'Run the following code only when the account is absent.
bash
account_body="$(jq -nc --arg uid "$CUSTOMER_UID" \
'{uid:$uid,account_type:"USER",metadata:{source:"quickstart"}}')"
account_response="$(wallet_request POST '/accounts' "$account_body")"
printf '%s\n' "$account_response" | jq
export ACCOUNT_ID="$(printf '%s' "$account_response" | jq -er '.data.account_id // empty')"Use GET /accounts/{account_id} to verify uid, account_type: USER, and status: ACTIVE, then store the customer mapping. If the create response is lost, query the account list for the same uid first.
3. Issue a deposit address
Call POST /accounts/{account_id}/deposit-addresses with numeric asset_type_id and network_id. Store the returned address, network, and tag_or_memo together.
bash
address_body="{\"asset_type_id\":$ASSET_TYPE_ID,\"network_id\":$NETWORK_ID}"
address_response="$(wallet_request POST "/accounts/$ACCOUNT_ID/deposit-addresses" "$address_body")"
printf '%s\n' "$address_response" | jq4. Verify the wallet
bash
wallet_request GET "/accounts/$ACCOUNT_ID" | jq
wallet_request GET "/accounts/$ACCOUNT_ID/balances" | jqContinue with the Wallet tutorial for deposits and withdrawals or the Digital Payment tutorial for customer-to-business payments.
Completion criteria
The quickstart is complete when:
- repeated provisioning reuses the same intended account rather than creating duplicates;
- the stored deposit destination includes network and memo information;
- balance amounts remain strings or decimal-safe values;
- all failed responses retain their upstream
request_id; and - rerunning read steps is safe.
Do not send real assets during quickstart. Use the test network and verify the selected asset deployment is active before requesting faucet or test-token funds.