Getting Started

Make your first calls to the Crypto as a Service API in minutes: connectivity, login, credentials, users, tokens, wallets, and deposit addresses.

This guide walks the path end to end—confirm connectivity, log in, register your customer, mint your API key, create and activate a user, issue their token, and give them a wallet with a deposit address. You go from zero to a funded address in minutes.

Conventions

  • Envelope: every response is { success, data | errors, meta: { timestamp, version, trace_id } }; lists add meta.pagination.
  • Money: amounts are decimal strings ("0.01000000"), never JSON numbers.
  • Statuses and enums: UPPER_SNAKE (PENDING, VERIFIED, BITCOIN).
  • Lists: cursor pagination with filter[limit] and cursor, filters as filter[where][field][op].
  • Retries: send x-idempotency-key (a UUID) on every POST and PATCH.
  • Auth by audience: Authorization: Bearer (account session) for SX Customers · x-api-key (owner) for SX Connect · Authorization: Bearer (user token) for SX Users.

Read API conventions for the details.

Prerequisites

You'll need:

  1. A Sovera account—your login email, password, and the customer_id issued when you registered. See Authentication for the full three-tier flow.
  2. An HTTP client—cURL, Postman, or your language's client.

Quick Start

Step 1: Test Connectivity

Hit the health endpoint to confirm you can reach the API. It needs no authentication and answers 200 with status: "PASS" in the standard envelope while the service is up—a quick way to rule out network or base-URL problems before you debug credentials.

GEThttps://api.sandbox.sovera.io/sovx/v1/health
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/health"

Response (200 OK):

{
  "success": true,
  "data": {
    "object": "health",
    "status": "PASS"
  },
  "meta": {
    "timestamp": "2026-10-12T14:00:00Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}

Step 2: Log in

Authenticate with your Sovera account email and password. Login returns a session object; send its token as Authorization: Bearer <token> on SX Customers calls.

POSThttps://api.sandbox.sovera.io/sovx/v1/auth/login
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "your-password"
  }'

Response (200 OK):

{
  "success": true,
  "data": {
    "object": "session",
    "token_type": "BEARER",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NWYxYzJhOSIsImV4cCI6MTc5MTgyMDIwMH0.Qm9ndXNTaWduYXR1cmVGb3JFeGFtcGxlT25seQ",
    "expires_at": "2026-10-12T15:30:00Z",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NWYxYzJhOSIsInR5cCI6InJlZnJlc2giLCJleHAiOjE3OTI0MjE0MDB9.UmVmcmVzaFNpZ25hdHVyZUV4YW1wbGU",
    "refresh_token_expires_at": "2026-10-19T14:30:00Z"
  },
  "meta": {
    "timestamp": "2026-10-12T14:30:00Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}

One session at a time

Each login or refresh retires the session token issued before it. Keep one session per account, store the newest token and refresh_token every time, and renew with Refreshing the session instead of logging in again.

Step 3: Register Your Customer

Register the customer that anchors your integration, with the Bearer token from Step 2. customer_id isn't a name you invent—it's the id your Sovera account already owns. An id your session doesn't own answers 404 CUSTOMER_NOT_FOUND, and one you've already registered answers 409 CUSTOMER_ALREADY_EXISTS. The response is the full customer resource; see Create Customer.

POSThttps://api.sandbox.sovera.io/sovx/v1/customers
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/customers" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -H "x-idempotency-key: 9a7c3e1f-5b2d-4c8e-a6f0-1d3b5e7f9a2c" \
  -d '{
    "customer_id": "corp-redundant-firewall",
    "email": "[email protected]",
    "entity_name": "Hedge Fund e-commerce"
  }'

Step 4: Generate API Credentials

Mint your owner API key with the Bearer token. The response is the credential resource; its customer_secret is the x-api-key you send on every SX Connect call. It's shown only once, so store it now.

POSThttps://api.sandbox.sovera.io/sovx/v1/customers/:customer_id/credentials
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/customers/corp-redundant-firewall/credentials" \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN"

Response (201 Created):

{
  "success": true,
  "data": {
    "id": "a3f1c2d4-5e6f-4081-92a3-b4c5d6e7f809",
    "object": "credential",
    "customer_id": "corp-redundant-firewall",
    "customer_secret": "uiFkvaYbt1YfBO2NiXyi1txbdysIxa8H",
    "customer_secret_prefix": "uiFkvaYb",
    "is_owner": true,
    "is_active": true,
    "user_email": "[email protected]",
    "user_name": "Hedge Fund e-commerce",
    "expires_at": null,
    "last_used_at": null,
    "created_at": "2026-10-12T14:05:00Z",
    "updated_at": "2026-10-12T14:05:00Z",
    "created_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd",
    "updated_by": "1d8cb40d-8740-5a6b-94c3-7406e08ab4fd"
  },
  "meta": {
    "timestamp": "2026-10-12T14:05:00Z",
    "version": "v1",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}

Step 5: Create and Activate a User

With your owner x-api-key, create the user who'll own the wallet. Enums are UPPER_SNAKE: account_type is INDIVIDUAL or CORPORATE, account_role is THIRD, and account_purpose is TRADING or INVESTING. Send identity details under individual. Every user starts PENDING.

POSThttps://api.sandbox.sovera.io/sovx/v1/users
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_OWNER_API_KEY" \
  -H "x-idempotency-key: 3d5f7a9b-1c2e-4f6a-8b0d-2e4f6a8c0b1d" \
  -d '{
    "external_id": "crm-000123",
    "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": {
      "birth_date": "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"
    }
  }'

The response (201 Created) is the user resource with its id and "status": "PENDING"; the full identity number never comes back, only individual.id_number_masked. Email, phone number, and external_id are unique per customer—a duplicate answers 409 EMAIL_ALREADY_IN_USE, PHONE_ALREADY_IN_USE, or EXTERNAL_ID_ALREADY_IN_USE. See Create User.

Then activate the user. Tokens are only issued to verified, active users.

POSThttps://api.sandbox.sovera.io/sovx/v1/users/:user_id/activate
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/f4057807-52cf-4083-9ecb-283ef354fb2b/activate" \
  -H "x-api-key: YOUR_OWNER_API_KEY"

The response (200 OK) is the user resource with "status": "VERIFIED".

Step 6: Issue a User Token

Issue the token pair the user presents on SX Users calls. The access token lasts 24 hours; the refresh token lasts 30 days and renews the pair once, without your owner key. See User Tokens.

POSThttps://api.sandbox.sovera.io/sovx/v1/users/:user_id/tokens
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/f4057807-52cf-4083-9ecb-283ef354fb2b/tokens" \
  -H "x-api-key: YOUR_OWNER_API_KEY"

Response (201 Created):

{
  "success": true,
  "data": {
    "id": "bf1f8aa6-8b55-5650-8ee7-c7a9d29d0b5e",
    "object": "user_token",
    "user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
    "token": "utk_test_7Qm4Lr8Tz1V2x9Kf3Bn6Wd1Yb6Jk2Hc5Np8Rf2Lm6Tq",
    "token_last4": "9Vx3",
    "expires_at": "2026-10-13T14:30:00Z",
    "created_at": "2026-10-12T14:30:00Z",
    "created_by": "65f1c2a9e4b0a1d2c3f4a5b6",
    "refresh_token": "rt_9f2c4e7a1b3d5f80c6e2a4b8d1f3e5a79f2c4e7a1b3d5f80c6e2a4b8d1f3e5a7",
    "refresh_expires_at": "2026-11-11T14:30:00Z"
  },
  "meta": {
    "timestamp": "2026-10-12T14:30:01Z",
    "version": "v1",
    "trace_id": "7d2a9c4e1f3b5a6c8e0d2f4a6b8c0e1d"
  }
}

Step 7: Create a Wallet

Give the user a wallet, acting as the user with their token. networks is an array of { network, currency } pairs with canonical network codes such as BITCOIN or ETHEREUM; each pair provisions a deposit address, returned in addresses[]. Call List Vault Networks to see what your vault supports.

POSThttps://api.sandbox.sovera.io/sovx/v1/users/:user_id/wallets
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" \
  -H "x-idempotency-key: 2c4e6a8b-1d3f-4a5c-9e7b-0f2d4c6e8a1b" \
  -d '{
    "name": "Main Wallet",
    "wallet_type": "VIRTUAL",
    "networks": [
      { "network": "BITCOIN", "currency": "BTC" }
    ]
  }'

Response (201 Created):

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "object": "wallet",
    "user_id": "f4057807-52cf-4083-9ecb-283ef354fb2b",
    "customer_id": "corp-redundant-firewall",
    "name": "Main Wallet",
    "description": null,
    "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": "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx",
        "memo": null,
        "created_at": "2026-10-12T14:31:05Z",
        "created_by": "66a0e1b2c3d4e5f6a7b8c9d0"
      }
    ],
    "created_at": "2026-10-12T14:31:05Z",
    "updated_at": "2026-10-12T14:31:05Z",
    "created_by": "66a0e1b2c3d4e5f6a7b8c9d0",
    "updated_by": "66a0e1b2c3d4e5f6a7b8c9d0"
  },
  "meta": {
    "timestamp": "2026-10-12T14:31:05Z",
    "version": "v1",
    "trace_id": "1e3c5a7b9d0f2e4a6c8b0d2f4e6a8c0b"
  }
}

You already have a deposit address

Creating the wallet provisions an address for each { network, currency } pair—read it from data.addresses. Step 8 is for an additional address on a wallet that already exists.

Step 8: Generate a Deposit Address

Add an address for another currency or network. Both currency and network are required. If the wallet already has an address for that pair, you get it back with 200 OK instead of 201 Created. See Wallet Addresses.

POSThttps://api.sandbox.sovera.io/sovx/v1/wallets/:wallet_id/addresses
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/wallets/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d/addresses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_USER_TOKEN" \
  -d '{
    "currency": "ETH",
    "network": "ETHEREUM"
  }'

Response (201 Created):

{
  "success": true,
  "data": {
    "id": "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
    "address_id": "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
    "object": "address",
    "wallet_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "currency": "ETH",
    "network": "ETHEREUM",
    "address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
    "memo": null,
    "created_at": "2026-10-12T14:32:40Z",
    "created_by": "66a0e1b2c3d4e5f6a7b8c9d0"
  },
  "meta": {
    "timestamp": "2026-10-12T14:32:40Z",
    "version": "v1",
    "trace_id": "5f7b9d1e3a5c7e9b1d3f5a7c9e1b3d5f"
  }
}

That's the full path—from a health check to a funded address.

Next Steps

  1. User onboarding flow—the complete user setup.
  2. Trading flow—quote and execute trades.
  3. Withdrawal flow—send crypto out with code verification.
  4. Webhooks—receive verification codes and events. Register your endpoint in Customer webhooks.

Common Issues

Every error returns the standard envelope—read errors[0].code, errors[0].message, and errors[0].source to see exactly what failed, and check Error Codes for the full list.

Authentication Failed (401)

  • Check the header: x-api-key for owner calls, Authorization: Bearer for sessions and user tokens.
  • Make sure the key isn't revoked and the user token is less than 24 hours old; renew it with its refresh token.

Rate Limit Exceeded (429)

  • Read x-rate-limit-remaining and x-rate-limit-reset on every response authenticated with an x-api-key or a user token.
  • On 429, wait the retry-after seconds before retrying.

Validation Error (422)

  • source.pointer names the body field that failed, source.parameter the path or query parameter.
  • Unknown body fields are rejected (a few reserved names are dropped silently)—send only the documented fields.

Support

On this page