SX Users

Wallets

Create custodial wallets for a user, list them, and read each wallet's balances and ledger.

Create custodial wallets for an end user, list the ones they hold, and read each wallet's balances and ledger. A wallet groups one or more network/currency pairs and provisions a deposit address per network when it's created. The user must already exist under your customer 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 only reaches its own user and its own wallets.

x-api-key: YOUR_OWNER_API_KEY

Responses use the standard envelope, amounts are decimal strings at each asset's scale, and lists use cursor pagination. See API conventions for the envelope, errors, idempotency, pagination and filters, money, and network codes.

A wallet you can't see answers exactly like a missing one: 404 WALLET_NOT_FOUND. That covers wallets of another customer and, for user tokens, wallets of another user.


The wallet object

FieldTypeDescription
idstring (UUID)Wallet id.
wallet_idstring (UUID)Same value as id, kept as an alias.
objectstringAlways wallet.
user_idstring (UUID)Owner of the wallet.
customer_idstringYour customer id.
namestringWallet name, unique per user.
descriptionstring | nullFree-text description.
wallet_typestringVIRTUAL or REAL.
statusstringACTIVE or RETIRED. FLAGGED and FROZEN are reserved for a later release; treat the enum as open.
networksarrayThe {network, currency} pairs the wallet was opened with. network is a canonical code such as BITCOIN.
addressesarrayDeposit addresses already provisioned, as address objects. Empty while provisioning; create one later with POST /wallets/{wallet_id}/addresses.
created_at / updated_atstringUTC timestamps without milliseconds.
created_by / updated_bystring | nullActor that created or last changed the wallet.

Create Wallet

POSThttps://api.sandbox.sovera.io/sovx/v1/users/:user_id/wallets

Open a new wallet for the user. Each network/currency pair you list provisions a deposit address, returned in addresses[]. Send an x-idempotency-key header (UUID) so a retry never opens a second wallet.

Path Parameters

ParameterTypeRequiredDescription
user_idstring (UUID)YesUser that owns the wallet.

Request Body

FieldTypeRequiredDescription
namestringYesWallet name, unique per user (max 100).
networksarrayYesOne or more network/currency pairs.
wallet_typestringNoVIRTUAL or REAL, case-insensitive. Defaults to VIRTUAL.
descriptionstringNoFree-text description.

networks[] object

FieldTypeRequiredDescription
networkstringYesCanonical network code: BITCOIN, ETHEREUM, SOLANA, TRON, POLYGON, or BNB_SMART_CHAIN.
currencystringYesCurrency code, e.g. BTC, ETH, USDC.
namestringNoDeprecated. The old network identifier (e.g. networks/bitcoin-testnet). Still accepted when network is missing; removed in the next release.
{
  "name": "Main Wallet",
  "description": "Main wallet for all transactions",
  "wallet_type": "VIRTUAL",
  "networks": [
    { "network": "BITCOIN", "currency": "BTC" }
  ]
}

Success Response (201 Created):

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "object": "wallet",
    "user_id": "3afd8834-33a7-52b0-aa47-8138c9af062a",
    "customer_id": "corp-redundant-firewall",
    "name": "Main Wallet",
    "description": "Main wallet for all transactions",
    "wallet_type": "VIRTUAL",
    "status": "ACTIVE",
    "networks": [
      { "network": "BITCOIN", "currency": "BTC" }
    ],
    "addresses": [
      {
        "id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
        "address_id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
        "object": "address",
        "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "currency": "BTC",
        "network": "BITCOIN",
        "address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
        "memo": null,
        "created_at": "2026-10-12T14:03:11Z",
        "created_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a"
      }
    ],
    "created_at": "2026-10-12T14:03:11Z",
    "updated_at": "2026-10-12T14:03:11Z",
    "created_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a",
    "updated_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a"
  },
  "meta": { "timestamp": "2026-10-12T14:03:11Z", "version": "v1", "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" }
}
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" \
  -H "x-idempotency-key: 9a7c3e1f-5b2d-4c8e-a6f0-1d3b5e7f9a2c" \
  -d '{
    "name": "Main Wallet",
    "description": "Main wallet for all transactions",
    "wallet_type": "VIRTUAL",
    "networks": [{ "network": "BITCOIN", "currency": "BTC" }]
  }'

Errors: 400 WALLET_NAME_ALREADY_EXISTS the user already has a wallet with that name · 401 UNAUTHORIZED invalid key or token · 403 FORBIDDEN a user token for another user · 404 USER_NOT_FOUND the user doesn't exist under your customer · 422 VALIDATION_ERROR invalid field, with source.pointer (e.g. /networks/0/network for an unknown network) · 429 RATE_LIMIT_EXCEEDED.


List Wallets

GEThttps://api.sandbox.sovera.io/sovx/v1/users/:user_id/wallets

List the user's wallets, newest first. A user with no wallets returns 200 with data: [].

Query Parameters

ParameterTypeRequiredDescription
filter[limit]integerNoPage size. Default 25, max 100.
cursorstringNoOpaque cursor from meta.pagination.navigation.
filter[order]stringNocreated_at or updated_at, ASC or DESC. Default created_at DESC.
filter[where][status][eq|inq]stringNoACTIVE, RETIRED (FLAGGED and FROZEN are accepted and match nothing today).
filter[where][created_at][gte|lte|between]stringNoUTC date-time ending in Z.
GET https://api.sandbox.sovera.io/sovx/v1/users/{{userID}}/wallets?filter[where][status][eq]=ACTIVE&filter[limit]=25

Success Response (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "object": "wallet",
      "user_id": "3afd8834-33a7-52b0-aa47-8138c9af062a",
      "customer_id": "corp-redundant-firewall",
      "name": "Main Wallet",
      "description": "Main wallet for all transactions",
      "wallet_type": "VIRTUAL",
      "status": "ACTIVE",
      "networks": [
        { "network": "BITCOIN", "currency": "BTC" }
      ],
      "addresses": [
        {
          "id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
          "address_id": "ad1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d",
          "object": "address",
          "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
          "currency": "BTC",
          "network": "BITCOIN",
          "address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
          "memo": null,
          "created_at": "2026-10-12T14:03:11Z",
          "created_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a"
        }
      ],
      "created_at": "2026-10-12T14:03:11Z",
      "updated_at": "2026-10-12T14:03:11Z",
      "created_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a",
      "updated_by": "d5263d12-b5e8-5fc7-ba07-816c0c78a61a"
    }
  ],
  "meta": {
    "timestamp": "2026-10-12T14:05:02Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "pagination": {
      "records": { "limit": 25, "has_next": false, "has_previous": false },
      "navigation": { "next": null, "previous": null }
    }
  }
}
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/users/{{userID}}/wallets?filter[where][status][eq]=ACTIVE&filter[limit]=25" \
  -H "x-api-key: YOUR_OWNER_API_KEY"

Errors: 401 UNAUTHORIZED · 403 FORBIDDEN a user token for another user · 404 USER_NOT_FOUND · 422 VALIDATION_ERROR unknown filter, operator, or cursor, with source.parameter · 429 RATE_LIMIT_EXCEEDED.


Get Wallet Balance

GEThttps://api.sandbox.sovera.io/sovx/v1/wallets/:wallet_id/balance

Read the wallet's balance per currency. Every amount is a decimal string at the asset's scale (BTC 8, ETH 18, USDT 6…). held is total minus available, never negative.

Response Fields

FieldTypeDescription
objectstringAlways wallet_balance.
wallet_idstring (UUID)Wallet id.
user_idstring (UUID)Owner of the wallet.
balances[]arrayOne row per currency.
balances[].currencystringUppercase currency code.
balances[].totalstringTotal balance.
balances[].availablestringAvailable to spend.
balances[].heldstringReserved by pending movements.
as_ofstringUTC time the balance was read.
GET https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/balance

Success Response (200 OK):

{
  "success": true,
  "data": {
    "object": "wallet_balance",
    "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "user_id": "3afd8834-33a7-52b0-aa47-8138c9af062a",
    "balances": [
      { "currency": "BTC", "total": "0.50000000", "available": "0.45000000", "held": "0.05000000" },
      { "currency": "ETH", "total": "1.250000000000000000", "available": "1.250000000000000000", "held": "0.000000000000000000" }
    ],
    "as_of": "2026-10-12T14:03:11Z"
  },
  "meta": { "timestamp": "2026-10-12T14:03:11Z", "version": "v1", "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" }
}
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/balance" \
  -H "x-api-key: YOUR_OWNER_API_KEY"

Errors: 401 UNAUTHORIZED · 404 WALLET_NOT_FOUND · 429 RATE_LIMIT_EXCEEDED.


List Wallet Transactions

GEThttps://api.sandbox.sovera.io/sovx/v1/wallets/:wallet_id/transactions

List the ledger movements recorded against this wallet, newest first. Only this wallet's movements come back; a wallet with none returns data: []. Each item is a transaction object.

Query Parameters

ParameterTypeRequiredDescription
filter[limit]integerNoPage size. Default 25, max 100.
cursorstringNoOpaque cursor from meta.pagination.navigation.
filter[order]stringNocreated_at or updated_at, ASC or DESC. Default created_at DESC.
filter[where][status][eq|inq]stringNoPENDING, PROCESSING, COMPLETED, FAILED, CANCELLED, EXPIRED, BLOCKED.
filter[where][currency][eq|inq]stringNoCurrency code, case-insensitive exact match.
filter[where][tx_hash][eq]stringNoOn-chain transaction hash.
filter[where][idempotency_key][eq]stringNox-idempotency-key of the request that created the movement.
filter[where][created_at][gte|lte|between]stringNoUTC date-time ending in Z.
GET https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/transactions?filter[where][status][inq][]=COMPLETED&filter[limit]=25

Success Response (200 OK):

{
  "success": true,
  "data": [
    {
      "id": "75ea771d-561e-5a7e-95b8-9420fe57aa55",
      "object": "transaction",
      "type": "DEPOSIT",
      "status": "COMPLETED",
      "status_reason": null,
      "customer_id": "corp-redundant-firewall",
      "user_id": "3afd8834-33a7-52b0-aa47-8138c9af062a",
      "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "currency": "BTC",
      "amount": "0.01000000",
      "fee": null,
      "net_amount": "0.01000000",
      "price": null,
      "pair": null,
      "balance_after": "0.51000000",
      "references": {
        "order_id": null,
        "withdrawal_id": null,
        "transfer_id": null,
        "deposit_id": "75ea771d-561e-5a7e-95b8-9420fe57aa55"
      },
      "address": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
      "network": "BITCOIN",
      "memo": null,
      "tx_hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
      "idempotency_key": null,
      "description": "Deposit credited",
      "created_at": "2026-10-11T09:12:40Z",
      "updated_at": "2026-10-11T09:31:02Z",
      "completed_at": "2026-10-11T09:31:02Z",
      "created_by": "system:integration-layer",
      "updated_by": "system:integration-layer"
    }
  ],
  "meta": {
    "timestamp": "2026-10-12T14:03:11Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "pagination": {
      "records": { "limit": 25, "has_next": true, "has_previous": false },
      "navigation": {
        "next": "/v1/wallets/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d/transactions?filter[where][status][inq][]=COMPLETED&filter[limit]=25&cursor=LGHoC3t43si9_yVEikVSoItl",
        "previous": null
      }
    }
  }
}
curl -g -X GET "https://api.sandbox.sovera.io/sovx/v1/wallets/{{walletID}}/transactions?filter[where][status][inq][]=COMPLETED&filter[limit]=25" \
  -H "x-api-key: YOUR_OWNER_API_KEY"

Errors: 401 UNAUTHORIZED · 404 WALLET_NOT_FOUND · 422 VALIDATION_ERROR unknown filter, operator, or cursor, with source.parameter · 429 RATE_LIMIT_EXCEEDED.

On this page