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 authentication | No auth headers or Bearer token provided | Include X-GAIAEX-APIKEY + X-GAIAEX-TIMESTAMP + X-GAIAEX-SIGNATURE headers, or Authorization: Bearer |
| 401 | Invalid API key | The API key does not exist or has been revoked | Create a new API key via dashboard or API |
| 401 | Invalid signature | HMAC signature verification failed | Check your signing logic: message = timestamp + METHOD + path + body |
| 401 | Timestamp expired | X-GAIAEX-TIMESTAMP is more than 5 seconds from server time | Sync your clock using GET /time |
| 401 | Session expired | Bearer session token 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 | Insufficient permissions | API key lacks the required permission (e.g., trade) | Update key permissions via PATCH /api-keys/{key} |
| 403 | IP not whitelisted | 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. |
| 409 | Duplicate client_id | A client_id was reused for a different order | Use unique client_id values per order |
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. |
| 502 | Upstream unavailable | A downstream service GaiaEx depends on is temporarily unreachable | Retry with exponential backoff |
Order-specific Errors
| 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. - Use
POST /order/test— validate orders before placing them in production. - Log all responses — include the
timestampfield for debugging with support.