API Error Codes Reference
Complete list of GaiaEx API error codes, their causes, and recommended fixes for common integration issues.
Authentication Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 401 | Missing API key auth headers | Required HMAC headers absent (X-GAIAEX-APIKEY, X-GAIAEX-TIMESTAMP, X-GAIAEX-SIGNATURE); or no Authorization: Bearer token for session-authenticated paths | Include all three HMAC headers for API-key requests, or a valid Bearer token for session requests |
| 401 | Invalid API key | The API key does not exist or has been revoked | Create a new API key via the mobile app (passkey step-up required) |
| 401 | Invalid HMAC signature | HMAC signature verification failed | Check your signing logic: message = timestamp + METHOD + path + body |
| 401 | Timestamp outside recv_window ({recv_window}ms). Server time: {server_ms} | X-GAIAEX-TIMESTAMP is outside the key's recv_window (default 5000ms, configurable per-key) | Sync your clock using GET /time |
| 401 | Invalid or expired session token | Bearer session token is invalid or has expired | Re-authenticate via /user/handshake |
| 403 | Address mismatch | Authenticated user address does not match the request path/body user_address | Ensure the API key belongs to the same address |
| 403 | API key lacks 'read' permission / API key lacks 'trade' permission | API key does not have the specific permission required by this endpoint | Update key permissions via the GaiaEx mobile app (PATCH /api-keys/{key}) |
| 403 | IP {client_ip} not in API key whitelist | Request IP is not in the API key's whitelist | Add the IP to the whitelist or remove the restriction |
Rate Limit Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 429 | Rate limit exceeded | Too many requests in the current window | Wait for the duration in the Retry-After header |
| 429 | Handshake rate limit | Too many handshake attempts | Wait 10–15 seconds before retrying |
Order Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 400 | Price must be divisible by {tick} | Price does not match the symbol's tick size | Round the price to the correct decimal places |
| 400 | Order must have minimum value of $10 | Order notional value is below $10 | Increase order size or price |
| 400 | Order has invalid size | Size does not match the symbol's size decimals | Round size to valid step size |
| 400 | Order has invalid price | Price is zero, negative, or malformed | Use a valid positive decimal price |
| 400 | Symbol 'XYZ' is not supported | The symbol is not listed or has been delisted | Check GET /symbols/list for valid symbols |
| 400 | Trading is halted | The symbol is temporarily halted | Wait and retry. Check symbol status. |
| 400 | Insufficient margin | Not enough available balance for the order | Deposit more USDC or reduce position size |
| 400 | Order was never placed, already canceled, or filled | Cancel/modify target order no longer exists | Verify the order ID. After modify, use the new order ID. |
Position Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 404 | No open position found | Attempting to close a position that doesn't exist | Check GET /user/{addr}/positions first |
| 400 | Size exceeds position | Close size is larger than the open position | Use a smaller size or omit for full close |
Leverage Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 400 | Leverage exceeds maximum | Requested leverage exceeds the symbol's max | Check maxLeverage from GET /symbols/list |
| 400 | Cross margin is not allowed | Symbol only supports isolated margin | The backend auto-corrects this, but if you encounter it, set is_cross: false |
Deposit / Withdrawal Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 400 | Below minimum deposit | Deposit amount is below the minimum ($5) | Increase deposit amount |
| 400 | Insufficient balance for withdrawal | Withdrawal exceeds available balance | Check available balance first |
| 400 | Invalid withdrawal signature | EIP-712 signature is invalid or nonce mismatch | Re-fetch the withdrawal payload and sign again |
Spot Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 400 | Spot symbol not found | The spot pair is not available | Check GET /spot/symbols for valid pairs |
| 400 | Insufficient spot balance | Not enough tokens for the sell order | Check GET /spot/balance/{address} |
General Errors
| HTTP Code | Error Message | Cause | Solution |
|---|---|---|---|
| 422 | Validation error | Request body failed schema validation | Check the detail array for specific field errors |
| 500 | Internal server error | Unexpected server-side error | Retry after a brief delay. Report persistent issues. |
Order-specific Errors
Note: Errors originating from order execution (e.g. price constraints, insufficient margin, invalid symbol) are passed through from the upstream exchange engine. These errors originate at the exchange level, not from GaiaEx input validation.
| Condition | Cause | Solution |
|---|---|---|
Cancel rejected: Order was never placed, already canceled, or filled | The orderId is stale — usually because a prior /order/modify replaced it, or the order already filled/canceled. | Always use the orderId returned by the latest /order/modify response. Query GET /user/{address}/openOrders to reconcile if in doubt. |
Insufficient margin to place order | The account's available USDC does not cover the order's margin requirement. | Reduce size, reduce leverage, or deposit more USDC via the GaiaEx mobile app. |
NEEDS_TRANSFER (HTTP 449) | Deployer markets (xyz:, cash:, vntl:) require a one-time in-app transfer before first trade. | Open the GaiaEx mobile app and enter the market once — the app completes the transfer. API-key integrations cannot complete this step. |
Invalid signature | HMAC digest did not match. Common causes: path includes the /v1/trade prefix (it should not), body re-serialized between signing and sending, or timestamp in seconds rather than milliseconds. | Review the signing walkthrough in General Info. The computed signature for the canonical example must match byte-for-byte. |
Invalid timestamp | Client clock is more than 5 seconds off server time. | NTP-sync your client. Pass X-GAIAEX-TIMESTAMP in milliseconds. |
Best Practices
- Always check the
detailfield — it contains the human-readable error message. - Handle 429 gracefully — respect the
Retry-Afterheader and implement exponential backoff. - After
POST /order/modify— always update your local order ID to the new one returned. - Validate inputs client-side — check price/quantity against the symbol's tick size and min notional (from
GET /v1/trade/symbols/list) before submitting an order. - Log all responses — include the
timestampfield for debugging with support.