Wallets
Create custodial wallets for a user, list them, and read their balances and transaction history.
Create custodial wallets for an end user, list the ones they hold, and read each wallet's balances and transaction history. A wallet groups one or more network/currency pairs and provisions a deposit address per network on creation. The user must already exist and be active before you open a wallet.
Authentication: every endpoint on this page accepts your Owner API Key (x-api-key) or a user token (Authorization: Bearer). A user token can only act on its own wallets.
x-api-key: YOUR_OWNER_API_KEYAll requests accept an optional x-trace-id header for request tracking; if omitted, one is generated.
Create Wallet
Open a new wallet for the user. Each network/currency pair you list provisions a deposit address automatically, returned in addresses[]. The wallet name must be unique per user—reusing one returns 400 Bad Request.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Wallet name, unique per user (max 100). |
| networks | array | Yes | One or more network/currency pairs. At least one required. |
| wallet_type | string | No | One of virtual, real. Defaults to virtual. |
| description | string | No | Free-text description of the wallet. |
networks[] object
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Vault network identifier (e.g. networks/bitcoin-testnet, networks/solana-devnet). |
| currency | string | Yes | Currency code (e.g. btc, eth, sol). |
{
"name": "Main Wallet",
"description": "Main wallet for all transactions",
"wallet_type": "virtual",
"networks": [
{ "name": "networks/bitcoin-testnet", "currency": "btc" }
]
}Success Response (201 Created):
{
"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"
}
}curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/{{userID}}/wallets" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_OWNER_API_KEY" \
-d '{
"name": "Main Wallet",
"description": "Main wallet for all transactions",
"wallet_type": "virtual",
"networks": [
{ "name": "networks/bitcoin-testnet", "currency": "btc" }
]
}'Errors: 400 missing/invalid fields, duplicate wallet name, or no vault configured · 401 invalid key · 404 user not found · 500 server error.
List Wallets
List every wallet the user holds, with its provisioned addresses. Pagination lives under meta.pagination. A user with no wallets returns 404 Not Found.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| filter[limit] | number | No | Items per page (default: 20, max: 100). |
| filter[skip] | number | No | Offset. |
GET https://api.sandbox.sovera.io/sovx/v1/users/{{userID}}/wallets?filter[limit]=20&filter[skip]=0Success Response (200 OK):
{
"success": true,
"data": [
{
"vault_wallet_id": "wal_8f3a9d2c7e4a",
"wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"wallet_type": "virtual",
"user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
"name": "Main Wallet",
"description": "Main wallet for all transactions",
"networks": [
{ "name": "networks/bitcoin-testnet", "currency": "btc" }
],
"addresses": [
{
"address_id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
"currency": "btc",
"address": "tb1qexampleaddressxxxxxxxxxxxxxxxxxxxxxx",
"network": "networks/bitcoin-testnet"
}
],
"created_at": "2026-01-15T10:30: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",
"pagination": {
"records": { "skip": 0, "has_next": false, "has_previous": false, "total": 1, "limit": 20 },
"navigation": {
"first": "/users/{{userID}}/wallets?filter[limit]=20&filter[skip]=0",
"last": "/users/{{userID}}/wallets?filter[limit]=20&filter[skip]=0",
"previous": null,
"next": null
}
}
}
}curl -X GET "https://api.sandbox.sovera.io/sovx/v1/users/{{userID}}/wallets?filter[limit]=20&filter[skip]=0" \
-H "x-api-key: YOUR_OWNER_API_KEY"Errors: 401 invalid key · 404 user has no wallets · 500 server error.
Get Wallet Balance
Read the wallet's balances per currency from the internal balance cache. Amounts are strings with 8 decimal places; available is the spendable portion after any locks.
GET https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/balanceSuccess Response (200 OK):
{
"success": true,
"data": {
"wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
"balance": [
{
"currency": "btc",
"balance": "0.50000000",
"available": "0.45000000",
"held": "0.05000000"
}
]
},
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1",
"trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f"
}
}curl -X GET "https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/balance" \
-H "x-api-key: YOUR_OWNER_API_KEY"Errors: 401 invalid key · 404 wallet not found · 500 server error.
Get Wallet Transactions
Retrieve the wallet's transaction history, filtered to the wallet's own addresses. The response and filter[...] parameters match /accounts/transactions, with pagination under meta.pagination.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| filter[limit] | number | No | Items per page (default: 20, max: 100). |
| filter[skip] | number | No | Offset. |
| filter[sort] | string | No | Sort by date: ASC or DESC (default DESC). |
| filter[where][type] | string | No | Type/action. Accepts a comma-separated list (e.g. deposit,withdrawal). |
| filter[where][currency] | string | No | Currency code (e.g. btc, eth). |
| filter[where][status] | string | No | Transaction status (e.g. pending, done). |
| filter[where][from] | number | No | Start date, Unix timestamp in ms (inclusive). |
| filter[where][to] | number | No | End date, Unix timestamp in ms (inclusive). |
| filter[where][amount][gte] | number | No | Amount ≥ value. |
| filter[where][amount][lte] | number | No | Amount ≤ value. |
GET https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/transactions?filter[limit]=20&filter[skip]=0Success Response (200 OK):
{
"success": true,
"data": [
{
"id": 99938268,
"balance": 49071.06877634,
"transaction": {
"order_id": "11637477",
"trade_id": "71847575",
"client_id": "76f0b5a8-a683-4ee3-8b13-af3c807df325",
"idempotency_id": null,
"symbol": "usdt/usd",
"created_at": "2026-05-19T20:24:01.000Z",
"hash": "",
"action": "Sell",
"currency": "usd",
"memo": "",
"amount": 1004.95049505,
"net_proceeds": 1004.95049505,
"price": 1.00720535,
"fees": 10.04950495,
"status": "done",
"description": ""
}
}
],
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1",
"trace_id": "5b8f3a9d-2c7e-4a1b-9f6d-0e3c2b1a4d5f",
"pagination": {
"records": { "skip": 0, "has_next": false, "has_previous": false, "total": 1, "limit": 20 },
"navigation": {
"first": "/wallets/{{walletID}}/transactions?filter[limit]=20&filter[skip]=0",
"last": "/wallets/{{walletID}}/transactions?filter[limit]=20&filter[skip]=0",
"previous": null,
"next": null
}
}
}
}curl -X GET "https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/transactions?filter[limit]=20&filter[skip]=0" \
-H "x-api-key: YOUR_OWNER_API_KEY"Errors: 400 filter[limit] exceeds 100 · 401 invalid key · 404 wallet not found · 500 server error.
Next Steps
- Create a deposit address for an additional currency.
- Transfer funds between wallets.