Error Handling
Proper error handling ensures smooth gameplay and easier debugging. This page covers two sides:
- Operator → Game Provider responses — the HTTP status codes and envelope your Wallet API should return.
- Game Provider internal error codes — the codes you may observe in
code / message fields and in logs/support conversations.
1. Operator Response Contract
Your Wallet API should respond using standard HTTP status codes. Game Provider keys retry logic on these codes.
| HTTP |
Meaning |
Retried? |
200 |
Success |
— |
400 |
Bad request, validation error, malformed payload |
No |
401 |
Invalid signature, unknown public key, invalid session |
No |
402 |
Insufficient funds |
No |
404 |
User / session not found |
No |
409 |
Conflict — duplicate provider_tx_id with different body |
No (operator should return original response for true duplicates) |
5xx |
Transient failure (DB down, upstream timeout, unexpected error) |
Yes — see Retry Behavior |
Error Response Envelope
Return an envelope consistent with the success envelope, with data: null:
{
"code": 402,
"message": "Insufficient player balance",
"data": null
}
[!TIP]
5xx responses and timeouts trigger retries. Ensure every withdraw / deposit / rollback handler is idempotent by provider_tx_id so retries never double-charge a player.
2. Game Provider Error Codes
Errors surfaced by Game Provider (e.g. in logs you receive via support, or in response bodies when Game Provider rejects a launch/callback) use the codes below. HTTP status is set per code.
Session & Transaction
| Code |
Name |
HTTP |
Meaning |
10000 |
BET_ALREADY_EXISTS |
400 |
Bet transfer already exists for this round / provider_tx_id |
10001 |
WIN_ALREADY_EXISTS |
400 |
Win transfer already exists |
10008 |
DEPOSIT_TRANSFER_NOT_FOUND |
400 |
Deposit (win) not found |
10012 |
GAME_SESSION_EXPIRED |
400 |
Session expired |
10013 |
GAME_SESSION_NOT_FOUND |
400 |
Session not found |
10014 |
NO_WITHDRAW_FOUND |
400 |
No existing withdraw found for the given roundId |
10015 |
ROUND_REQUIRED |
400 |
roundId / action_id is required |
10016 |
GAME_DUPLICATE_ROUND |
409 |
Duplicate round ID |
10017 |
GAME_BALANCE_NOT_FOUND |
404 |
Balance not found |
10018 |
GAME_INVALID_SESSION |
401 |
Invalid session token |
20444 |
GAME_SESSION_INACTIVE |
400 |
Game session is not active |
Idempotency & Signature
| Code |
Name |
HTTP |
Meaning |
10002 |
MISSING_IDEMPOTENCY_KEY |
400 |
Missing idempotency key in request header (internal wallet call) |
10003 |
ALREADY_PROCESSING_IDEMPOTENCY_KEY |
409 |
Another request with the same idempotency key is already in-flight |
10003 |
INVALID_SIGNATURE |
401 |
X-Signature does not match computed HMAC |
10004 |
INVALID_PUBLIC_KEY |
400 |
X-Public-Key not recognized |
10030 |
IDEMPOTENCY_UNAVAILABLE |
503 |
Idempotency cache (Redis) unavailable |
Validation
| Code |
Name |
HTTP |
Meaning |
10009 |
INVALID_REQUEST_PARAMETERS |
400 |
Missing or invalid request parameters |
10010 |
INVALID_CURRENCY |
400 |
Invalid currency |
10011 |
INVALID_USER |
400 |
Invalid user information |
10019 |
INVALID_CLIENT_INFO |
400 |
Client information is required |
10020 |
INVALID_OPERATOR_TX_ID |
400 |
Operator transaction ID is required |
10021 |
INVALID_USER_ID |
400 |
User ID is required |
10022 |
INVALID_CURRENCY_CODE |
400 |
Currency code is required |
10023 |
INVALID_PORTAL_NAME |
400 |
Portal name is required |
10027 |
INVALID_BET_LEVEL |
400 |
Bet level must be > 0 |
10029 |
INVALID_PORTAL_PUBLIC_KEY |
400 |
Invalid portal public key |
10049 |
INVALID_REQUEST_FORMAT |
400 |
Invalid request format |
Operator-Response Errors
Returned by Game Provider when the Operator's response to a Game Provider callback is malformed or inconsistent.
| Code |
Name |
HTTP |
Meaning |
10008 |
OPERATOR_NO_RESPONSE |
400 |
No / invalid response from operator |
10009 |
OPERATOR_INVALID_RESPONSE |
400 |
Invalid amount from operator |
10010 |
OPERATOR_INVALID_CURRENCY |
400 |
Currency does not match session |
10010 |
OPERATOR_INVALID_USER |
400 |
user_id from operator does not match session |
10011 |
OPERATOR_INVALID_USER_BALANCE |
400 |
Negative balance returned |
10028 |
OPERATOR_INSUFFICIENT_FUNDS |
400 |
Operator rejected bet — insufficient funds |
Gifts / Free Bets
| Code |
Name |
HTTP |
Meaning |
10012 |
FAILED_TO_CANCEL_GIFT |
400 |
Gift cancellation failed |
10013 |
FAILED_TO_CONSUME_GIFT |
400 |
Gift consumption failed |
10014 |
FAILED_TO_GRANT_GIFT |
400 |
Gift grant failed |
10015 |
FREEBET_CONSUME_IS_NOT_VALID |
400 |
Cannot consume the free bet |
10016 |
FREEBET_NOT_AVAILABLE |
400 |
Free bet is not available |
10017 |
INVALID_AMOUNT |
400 |
Invalid amount |
10024 |
INVALID_GIFTS_LIST |
400 |
At least one gift is required |
10025 |
INVALID_GIFT_KEY |
400 |
Gift key is required |
10026 |
INVALID_GIFT_QUANTITY |
400 |
Quantity must be > 0 |
Casino / Configuration
| Code |
Name |
HTTP |
Meaning |
10004 |
CASINO_CONFIG_NOT_FOUND |
404 |
Casino configuration not found |
30001 |
CASINO_NOT_REGISTERED |
400 |
Casino not registered |
30002 |
CASINO_INVALID_KEY |
401 |
API key invalid |
Server-Driven (V2) Integration
Surfaced only for server-driven titles (e.g. Aviadrone). Operators generally never see these unless they run the provider-launch flow themselves.
| Code |
Name |
HTTP |
Meaning |
10050 |
V2_SESSION_NOT_FOUND |
400 |
V2 session not found |
10051 |
V2_SESSION_NOT_ACTIVE |
400 |
V2 session is not active |
10052 |
V2_SESSION_EXPIRED |
400 |
V2 session has expired |
10053 |
V2_PARENT_TRANSACTION_NOT_FOUND |
400 |
Parent transaction not found for the given parentTransactionId |
10054 |
V2_INVALID_AMOUNT |
400 |
Invalid amount format in v2 request |
10055 |
V2_DUPLICATE_EXTERNAL_TX_ID |
409 |
Duplicate external transaction ID |
10056 |
PROVIDER_LAUNCH_FAILED |
502 |
Game provider launch call failed |
10057 |
V2_INVALID_REQUEST |
400 |
Invalid v2 request parameters |
System
| Code |
Name |
HTTP |
Meaning |
20001 |
SYSTEM_TIMEOUT |
504 |
Request timed out |
20002 |
SYSTEM_INTERNAL_ERROR |
500 |
Internal server error |