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 addmeta.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]andcursor, filters asfilter[where][field][op]. - Retries: send
x-idempotency-key(a UUID) on everyPOSTandPATCH. - 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:
- A Sovera account—your login email, password, and the
customer_idissued when you registered. See Authentication for the full three-tier flow. - 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.
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.
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.
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.
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.
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.
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.
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.
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.
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
- User onboarding flow—the complete user setup.
- Trading flow—quote and execute trades.
- Withdrawal flow—send crypto out with code verification.
- 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-keyfor owner calls,Authorization: Bearerfor 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-remainingandx-rate-limit-reseton every response authenticated with anx-api-keyor a user token. - On
429, wait theretry-afterseconds before retrying.
Validation Error (422)
source.pointernames the body field that failed,source.parameterthe path or query parameter.- Unknown body fields are rejected (a few reserved names are dropped silently)—send only the documented fields.
Support
- Email: [email protected]
- Documentation: https://docs.sovera.io
Introduction
Build on Sovera Crypto as a Service: onboard users, hold and move crypto, trade, and pay out over one REST API.
Authentication
Authenticate in three tiers: account login (Bearer session), customer API credentials (owner x-api-key), then per-user tokens (Bearer, 24 hours with a 30-day refresh token).