User Onboarding Workflow
Complete guide to onboarding a new user: create an account, generate a token, create a wallet, and generate a deposit address.
Onboarding turns a brand-new person into an account that can hold crypto, trade, and withdraw. This guide walks the full sequence end to end, in the order the API expects it.
Overview
Each step builds on the one before it. You create the user with your owner key, mint a token so that user can act on its own behalf, give the user a wallet to hold funds, then generate an address so money can flow in.
- Create a user account
- Generate an authentication token
- Create a wallet
- Generate a deposit address
When you finish, you'll hold a user_id, a user token, a wallet_id, and a deposit address — everything later flows like trading and withdrawals depend on.
Estimated time: 5-10 minutes
Prerequisites: your owner API key (x-api-key)
Authentication by step
Each step authenticates as the actor that performs it:
- Create and manage users, generate tokens — your owner key,
x-api-key: YOUR_OWNER_API_KEY(SX Connect). - Act on the user (wallets, addresses) — the user token from Step 2, sent as
Authorization: Bearer YOUR_USER_TOKEN.
Step-by-Step Guide
Step 1: Create User Account
Start by registering the person. This creates the identity that owns every wallet, balance, and transaction that follows. Send the holder's KYC details under individual.
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_OWNER_API_KEY" \
-d '{
"account_type": "individual",
"account_role": "third",
"account_purpose": "investing",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone_country_code": "US",
"phone_number": "2252542523",
"individual": {
"dob": "1990-10-15",
"residential_country_code": "US",
"residential_address": "123 Sovera Lane",
"residential_city": "Cheyenne",
"residential_state": "WY",
"residential_postal_code": "82001",
"id_type": "ssn",
"id_number": "123456789",
"id_country_code": "US"
}
}'Response:
{
"success": true,
"data": {
"account_type": "individual",
"account_role": "third",
"account_purpose": "investing",
"user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"phone_country_code": "US",
"phone_number": "2252542523",
"status": "PENDING",
"created_at": "2026-01-15T10:30:00.000Z",
"updated_at": "2026-01-15T10:30:00.000Z",
"individual": {
"dob": "1990-10-15",
"residential_country_code": "US",
"residential_address": "123 Sovera Lane",
"residential_city": "Cheyenne",
"residential_state": "WY",
"residential_postal_code": "82001",
"id_type": "ssn",
"id_number": "123456789",
"id_country_code": "US"
}
},
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1",
"trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f"
}
}Save the user_id. Every later step — token, wallet, address — is scoped to it. A new user starts in PENDING and moves to VERIFIED once KYC clears.
See Create User for full request details.
Step 2: Generate User Authentication Token
The user now exists, but it can't act on its own yet. Use your owner key to mint a token so calls can be made on the user's behalf. Calling this again for the same user issues a fresh token and invalidates the previous one.
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/f4057807-52cf-4083-9ecb-283ef354fb2b/token" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_OWNER_API_KEY"Response:
{
"success": true,
"data": {
"token": "012d23b0d9a7d6c7d0b0429963eece727c4eca18635978d0bd6ffe6d1eaaed10",
"user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
"expires": "2027-01-15T10:30:00.000Z"
},
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1",
"trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f"
}
}The user token is valid for one year (expires is an ISO 8601 timestamp). Save it and send it as Authorization: Bearer YOUR_USER_TOKEN for calls made on the user's behalf.
See Generate Token for full request details.
Step 3: Create Wallet
A wallet is where the user's crypto lives. Create one so the account has somewhere to receive deposits, settle trades, and fund withdrawals. Act as the user with the Bearer token from Step 2. Each network/currency pair provisions a deposit address, returned in addresses[].
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/f4057807-52cf-4083-9ecb-283ef354fb2b/wallets" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-d '{
"name": "Main Wallet",
"description": "Main wallet for all transactions",
"wallet_type": "virtual",
"networks": [
{ "name": "networks/bitcoin-testnet", "currency": "btc" }
]
}'Response:
{
"success": true,
"data": {
"vault_wallet_id": "wal_8f3a9d2c7e4a",
"wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"name": "Main Wallet",
"description": "Main wallet for all transactions",
"networks": [
{ "name": "networks/bitcoin-testnet", "currency": "btc" }
],
"is_active": true,
"created_at": "2026-01-15T10:30:00.000Z",
"wallet_type": "virtual",
"addresses": [
{
"address_id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
"currency": "btc",
"network": "networks/bitcoin-testnet",
"address": "tb1qexampleaddressxxxxxxxxxxxxxxxxxxxxxx"
}
]
},
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1",
"trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f"
}
}Save the wallet_id. Creating the wallet already provisions one address per network, but you can generate more for other currencies next.
See Create Wallet for full request details.
Step 4: Generate Deposit Address
Generate a deposit address so the user can fund the wallet — anyone can send the chosen currency to this address and it lands in the wallet. If the wallet already has an address for that currency and network, the existing one is returned. Act as the user with the Bearer token.
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/wallets/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d/address" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-d '{
"currency": "btc",
"network": "bitcoin-testnet"
}'Response:
{
"success": true,
"data": {
"wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"vault_wallet_id": "vault-7f3a2b1c",
"user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
"name": "Main Wallet",
"description": "Primary trading wallet",
"addresses": [
{
"address_id": "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"currency": "btc",
"network": "bitcoin-testnet",
"address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
}
],
"created_at": "2026-01-15T10:00:00.000Z",
"updated_at": "2026-01-15T10:30:00.000Z"
},
"meta": { "timestamp": "2026-01-15T10:30:00.000Z", "version": "v1", "trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f" }
}See Generate Address for full request details.
With an address in hand, onboarding is done: the user can receive funds and you can move on to trading or withdrawals.
Next Steps
After onboarding:
- Check Balance — Monitor the wallet balance
- Execute Trade — Start trading
- Process Withdrawal — Withdraw funds
Troubleshooting
User Already Exists
Error: 409 CONFLICT
Solution: The email, phone_number, or user_id is already in use. Use unique values or retrieve the existing user.
Validation Failed
Error: 422 UNPROCESSABLE_ENTITY
Solution: Check the field-level messages in errors[]. The phone_number must be a valid mobile number for the given phone_country_code, and the holder must be 18 or older.
Wallet Creation Failed
Error: 400 BAD_REQUEST
Solution: The name must be unique per user, and the customer must have a vault configured.
Support
Need help? Email [email protected]