Trading Workflow
Execute a trade end to end: pick a pair, lock a quote, place the order, track it, and check the wallet balance.
Trading on Sovera is quote-driven: you lock a price first, then place an order against it. This guide follows that sequence end to end, so the price you see is the price you trade at.
Overview
A trade always starts with a quote. The quote fixes the price and side for a few seconds; the order then executes that exact quote. Most orders settle on execution and come back COMPLETED. Read the order back by id to track it, and read the wallet balance to see the funds move.
- Pick a pair
- Request a quote
- Place an order against the quote
- Track the order
- Check the wallet balance
Prerequisites:
- Your Owner API Key (
x-api-key) or the user's token (Authorization: Bearer) - An active user with a wallet
- Enough balance to cover the trade and its fee
Every response uses the standard envelope. Amounts are decimal strings and pairs are BASE/QUOTE.
Step-by-Step Guide
Step 1: Pick a Pair
List the pairs you can quote. Send the pair value as-is in the next step.
curl -G "https://api.sandbox.sovera.io/sovx/v1/currencies/pairs" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
--data-urlencode "filter[limit]=100"Response:
{
"success": true,
"data": [
{
"object": "currency_pair",
"pair": "BTC/USD",
"base_currency": "BTC",
"quote_currency": "USD",
"is_trading_enabled": true
}
],
"meta": {
"timestamp": "2026-10-12T14:29:58Z",
"version": "v1",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"pagination": {
"records": { "limit": 100, "has_next": false, "has_previous": false },
"navigation": { "next": null, "previous": null }
}
}
}See List Trading Pairs for full details.
Step 2: Request a Quote
Lock a price before you commit. A quote pins the pair, side, and size to one price, so the order in the next step executes at a known rate. Send exactly one of quantity (base currency) or amount (quote currency), as a decimal string. Add an x-idempotency-key so a retried request doesn't create a second quote.
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/90f904da-dc14-535e-b2db-56be50db02c8/trading/quotes" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-H "x-idempotency-key: 6f1c2a7e-9b3d-4f5a-8c2e-1d7b9a0e4c33" \
-d '{
"pair": "BTC/USD",
"side": "BUY",
"quantity": "0.01000000"
}'Response:
{
"success": true,
"data": {
"id": "be27cd3f-3276-523e-a48c-f0661a079e72",
"quote_id": "be27cd3f-3276-523e-a48c-f0661a079e72",
"object": "quote",
"status": "OPEN",
"wallet_id": "90f904da-dc14-535e-b2db-56be50db02c8",
"user_id": "43ac9e63-96c4-5f50-b788-dfbc6b265375",
"pair": "BTC/USD",
"base_currency": "BTC",
"quote_currency": "USD",
"side": "BUY",
"quantity": "0.01000000",
"amount": "450.0000",
"buy_price": "45000.0000",
"sell_price": null,
"fee": "4.5000",
"idempotency_key": "6f1c2a7e-9b3d-4f5a-8c2e-1d7b9a0e4c33",
"created_at": "2026-10-12T14:30:00Z",
"expires_at": "2026-10-12T14:30:15Z"
},
"meta": {
"timestamp": "2026-10-12T14:30:00Z",
"version": "v1",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}A quote is executable only until expires_at, usually a few seconds after created_at. Place the order right away or request a new quote.
See Request Quote for full details.
Step 3: Place the Order
Execute the quote. Pass its id as quote_id; the order takes the pair and side from the quote. Use a new x-idempotency-key: if the call times out, repeat it with the same key and you'll get the original order back instead of a second trade.
curl -X POST "https://api.sandbox.sovera.io/sovx/v1/users/90f904da-dc14-535e-b2db-56be50db02c8/trading/orders" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
-H "x-idempotency-key: 9a7c3e1f-5b2d-4c8e-a6f0-1d3b5e7f9a2c" \
-d '{
"quote_id": "be27cd3f-3276-523e-a48c-f0661a079e72"
}'Response (201 Created):
{
"success": true,
"data": {
"id": "168fc813-35b8-5447-89ed-07ec366f33c6",
"order_id": "168fc813-35b8-5447-89ed-07ec366f33c6",
"object": "order",
"status": "COMPLETED",
"status_reason": null,
"quote_id": "be27cd3f-3276-523e-a48c-f0661a079e72",
"transaction_id": "be2fa389-4b35-5c80-a830-2e849e9df31d",
"user_id": "43ac9e63-96c4-5f50-b788-dfbc6b265375",
"wallet_id": "90f904da-dc14-535e-b2db-56be50db02c8",
"customer_id": "corp-redundant-firewall",
"pair": "BTC/USD",
"base_currency": "BTC",
"quote_currency": "USD",
"side": "BUY",
"quantity": "0.01000000",
"price": "45000.0000",
"amount": "450.0000",
"fee": "4.5000",
"tx_hash": null,
"network": null,
"idempotency_key": "9a7c3e1f-5b2d-4c8e-a6f0-1d3b5e7f9a2c",
"created_at": "2026-10-12T14:30:04Z",
"updated_at": "2026-10-12T14:30:05Z",
"completed_at": "2026-10-12T14:30:05Z",
"created_by": "43ac9e63-96c4-5f50-b788-dfbc6b265375",
"updated_by": "43ac9e63-96c4-5f50-b788-dfbc6b265375"
},
"meta": {
"timestamp": "2026-10-12T14:30:05Z",
"version": "v1",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Read status to decide what's next:
COMPLETED—the trade settled. Go to Step 5.PENDINGorPROCESSING—accepted but not settled. Go to Step 4.FAILED—status_reason.codesays why.QUOTE_REJECTEDmeans the quote was rejected at execution and is now used up: request a new quote.
Save the order id. transaction_id links the trade to its row in the wallet's transaction history.
See Place Order for full details.
Step 4: Track the Order
Read the order by id, or list the wallet's open orders with a status filter.
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/users/90f904da-dc14-535e-b2db-56be50db02c8/trading/orders/168fc813-35b8-5447-89ed-07ec366f33c6" \
-H "Authorization: Bearer YOUR_USER_TOKEN"curl -G "https://api.sandbox.sovera.io/sovx/v1/users/90f904da-dc14-535e-b2db-56be50db02c8/trading/orders" \
-H "Authorization: Bearer YOUR_USER_TOKEN" \
--data-urlencode "filter[where][status][inq][]=PENDING" \
--data-urlencode "filter[where][status][inq][]=PROCESSING"Both return the same order object as Step 3. See Get Order and List Orders.
Step 5: Check the Wallet Balance
Confirm the outcome by reading the wallet balance. After a buy you'll see more of the bought asset and less of what you spent; a sell is the reverse.
curl -X GET "https://api.sandbox.sovera.io/sovx/v1/wallets/90f904da-dc14-535e-b2db-56be50db02c8/balance" \
-H "Authorization: Bearer YOUR_USER_TOKEN"Response:
{
"success": true,
"data": {
"object": "wallet_balance",
"wallet_id": "90f904da-dc14-535e-b2db-56be50db02c8",
"user_id": "43ac9e63-96c4-5f50-b788-dfbc6b265375",
"balances": [
{
"currency": "BTC",
"total": "0.01000000",
"available": "0.01000000",
"held": "0.00000000"
},
{
"currency": "USD",
"total": "9545.5000",
"available": "9545.5000",
"held": "0.0000"
}
],
"as_of": "2026-10-12T14:31:00Z"
},
"meta": {
"timestamp": "2026-10-12T14:31:00Z",
"version": "v1",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}See Wallets for full details.
Troubleshooting
Quote Expired
Error: 400 QUOTE_EXPIRED, with source.pointer /quote_id.
Solution: Request a new quote and place the order before its expires_at.
Quote Already Executed
Error: 422 INVALID_STATE_TRANSITION, with source.pointer /quote_id.
Solution: Each quote executes once. If you were retrying after a timeout, repeat the original request with the same x-idempotency-key to get the existing order, or read it with List Orders filtered by idempotency_key.
Order Failed
Issue: The order came back 201 with status: "FAILED" and status_reason.code: "QUOTE_REJECTED".
Solution: The quote was rejected at execution and is used up. Request a new quote.
Invalid Request
Error: 422 VALIDATION_ERROR. source.pointer names the field, e.g. /pair for a pair that isn't BASE/QUOTE, or /amount when you send both quantity and amount.
Solution: Fix the field and retry. Check the pair against List Trading Pairs.
Wallet or Quote Not Found
Error: 404 WALLET_NOT_FOUND or 404 QUOTE_NOT_FOUND.
Solution: Use a wallet that belongs to your customer (and to the user, with a user token), and a quote requested for that same wallet.
Best Practices
- Quote right before you trade—quotes live for seconds;
expires_atis the authority. - Check the balance first—confirm the wallet covers the trade and its fee.
- Send an idempotency key on every POST—a retry returns the original result instead of trading twice.
- Store the order id—use it to track the order and reconcile it with the wallet's history.
- Read
status, not the HTTP code—a rejected quote still returns201with aFAILEDorder.
Next Steps
- Account data—view balances and transaction history
- Withdrawals—send funds out
- Transfers—move funds between wallets
Support
Need help? Email [email protected]
User Onboarding Workflow
Complete guide to onboarding a new user: create the account, activate it, issue a token, create a wallet, and generate a deposit address.
Withdrawal Workflow
End-to-end guide to crypto withdrawals: initiate on a network, receive the verification code by webhook, confirm, and track the withdrawal until it settles on-chain.