Error Codes
This page lists all error codes returned by the Operator API, along with the status values the operator returns in wallet callbacks.
Error Response Shape
When the Operator API fails, it returns the JSON below together with an HTTP 4xx or 5xx status.
{
"error": {
"code": "INVALID_REQUEST",
"message": "invalid fields",
"details": { "fields": ["player.nickname"] }
}
}| Field | Type | Description |
|---|---|---|
error.code | string | Error code. Branch your program logic on this value |
error.message | string | Human-readable English description. The wording may change, so do not use it for branching |
error.details | object | Present only for some errors: fields (list of invalid field names) for field errors, and kind, key, conflicts for audit log revert errors |
- A request to an unregistered path or method returns HTTP 404 or 405 with a plain-text body rather than this JSON. Check for typos in the path or method first.
- Do not retry errors that will produce the same result if the request is resent unchanged (most 4xx errors). Errors that may be retried are roughly
RATE_LIMITED,INTERNAL_ERROR,TABLE_OPEN_FAILED,GAME_MAINTENANCE, andUNAVAILABLE. When retrying, you must sign again with a newX-TimestampandX-Nonce.
HTTP Status Summary
| HTTP | Meaning |
|---|---|
| 400 | Invalid request body or parameters |
| 401 | Signature, timestamp, or nonce verification failed |
| 403 | Authenticated but not permitted (operator status, IP, permissions) |
| 404 | The target does not exist or does not belong to this operator |
| 409 | Conflict with the current state |
| 429 | Rate limit exceeded |
| 500 | Platform internal error |
| 503 | Temporarily unavailable (maintenance, etc.) |
Authentication and Common Errors
These can occur on any endpoint. They are listed in the order in which they are checked. For detailed rules, see Authentication and Signing.
| code | HTTP | Cause | Action |
|---|---|---|---|
INVALID_SIGNATURE | 401 | X-Operator is not a registered code | Check the operator code |
OPERATOR_DISABLED | 403 | The operator is suspended | Contact the platform |
IP_NOT_ALLOWED | 403 | The request IP is not in the registered IP allowlist | Register the operator server's public outbound IP with the platform |
INVALID_SIGNATURE | 401 | X-Api-Key was sent but the value is wrong | Check the issued api_key (after reissue, the previous key becomes invalid immediately) |
INVALID_REQUEST | 400 | The request body could not be read | Check the body and Content-Length |
TIMESTAMP_OUT_OF_RANGE | 401 | X-Timestamp is not an integer or differs from platform time by more than 5 minutes | Send Unix milliseconds and synchronize the server clock with NTP |
INVALID_SIGNATURE | 401 | The signature does not match, or X-Nonce is empty or longer than 128 characters | Check the string to sign (timestamp, nonce, method, path + query, raw body) and api_secret. A body truncated for exceeding 64 KB also fails here |
NONCE_REUSED | 401 | The same X-Nonce was reused within 5 minutes | Generate a new nonce for each request, including retries, and sign again |
RATE_LIMITED | 429 | More than 200 requests per second per operator | Retry after a short wait; reduce call frequency and cache results |
INTERNAL_ERROR | 500 | Platform internal error | Retry after a short wait; contact the platform if it persists |
Endpoint-Specific Errors
| code | HTTP | Where | Meaning | Action |
|---|---|---|---|---|
INVALID_REQUEST | 400 | Every endpoint that accepts a body or parameters | The JSON is malformed or a field value is invalid. For field errors, details.fields lists the field names | Fix the fields in details.fields and resend |
CURRENCY_NOT_SUPPORTED | 400 | POST /launch | A currency not allowed for this operator | Check your contracted currencies (GET /currencies) |
CURRENCY_MISMATCH | 409 | POST /launch | Launch with a currency different from the existing player's currency | A player's currency is fixed at the first launch and never changes. Use a different external_id per currency |
PLAYER_BLOCKED | 403 | POST /launch | The player is blocked on the platform | To unblock, call POST /players/{external_id}/logout with block: false |
GAME_NOT_FOUND | 404 | POST /launch, table creation, per-game settings | The game code does not exist or the game is not enabled for this operator | Check enabled games with GET /games |
GAME_MAINTENANCE | 503 | POST /launch | The game is under maintenance | Launch again after maintenance ends. Show a maintenance notice in the lobby |
TABLE_NOT_FOUND | 404 | POST /launch, Tables | The table does not exist, is closed, belongs to another game, or is another operator's dedicated table | Check current tables with GET /tables |
PRIVATE_PASSWORD | 403 | POST /launch (table_password) | The private table password is wrong | Ask the player to enter it again |
RATE_LIMITED | 429 | POST /launch (table_password) | The same player attempted the same table's password more than 5 times in 1 minute | Try again after 1 minute |
TABLE_NOT_OWNED | 403 | Table changes, closing, per-table settings | Attempted to change a shared table rather than the operator's dedicated table | Only dedicated tables can be changed |
TABLE_CREATE_FORBIDDEN | 403 | POST /tables | The operating mode does not allow creating tables, or table creation is not allowed for that game | Agree on the operating mode and allowed games with the platform |
TEMPLATE_NOT_FOUND | 404 | POST /tables | There is no default table to copy for that game | Contact the platform |
TEMPLATE_NOT_ALLOWED | 400 | POST /tables | The table specified as the copy source cannot be used | Specify a different source table, or create the table from the game code without a source |
INVALID_CONFIG | 400 | Table creation, settings, timers, rake, live, currency | A setting value is out of the allowed range or values are inconsistent with each other | Correct the values using message as a guide |
UNSUPPORTED_GAME | 400 | PUT /tables/{table_id}/live | A game that does not support dealing or pause control | Use only on Live Hold'em and Speed Hold'em tables |
TABLE_BUSY | 409 | PUT /tables/{table_id}/currency | The currency cannot be changed because players are seated | Try again once the table is empty |
TABLE_OPEN_FAILED | 500 | POST /tables, PUT /tables/{table_id}/currency | The table could not be opened | Retry after a short wait; contact the platform if it persists |
UNAVAILABLE | 503 | POST /tables | Tables cannot be created right now | Retry after a short wait; contact the platform if it persists |
BAD_IMAGE | 400 | PUT /lobby-banners | Banner image format or size error | Upload again in an allowed format and size |
BANNER_NOT_FOUND | 404 | PUT /games/{game_code}/lobby | The specified banner image has not been uploaded yet | Upload the image first with PUT /lobby-banners |
ROUND_NOT_FOUND | 404 | GET /rounds/{round_id} | The round does not exist or does not belong to this operator or player | Check round_id and external_id |
SESSION_NOT_FOUND | 404 | GET /sessions/{session_id} | The table session does not exist | Check the tss_… ID |
PLAYER_NOT_FOUND | 404 | POST /players/{external_id}/logout | A player who has never launched a game | Check external_id |
DEALER_NOT_FOUND | 404 | Dealers | The dealer does not exist or does not belong to this operator | Check dealer_id |
DUPLICATE | 409 | POST /dealers | The dealer login ID is already in use (shared across all operators) | Use a different ID |
BAD_PHOTO | 400 | PUT /dealers/{dealer_id}/photo | Photo format or size error | Upload again in an allowed format and size |
CARD_LOG_FORBIDDEN | 403 | GET /dealer-card-log | The card input log is not available in this operating mode | independent operating mode only |
PRIVATE_FORBIDDEN | 403 | Private Tables | Private tables are not available in this operating mode | independent operating mode only |
PRIVATE_OVERLAP | 409 | POST /private-tables | The time overlaps with another reservation on the same table | Adjust the time slot |
PRIVATE_ENDED | 409 | DELETE /private-tables/{private_id} | The reservation has already ended or been cancelled | No need to cancel |
NOT_FOUND | 404 | DELETE /private-tables/{private_id}, POST /audit/{audit_id}/restore | The reservation or audit record does not exist | Check the ID |
NOT_RESTORABLE | 403 | POST /audit/{audit_id}/restore | A type of change the operator cannot revert | Contact the platform |
NOT_RESTORABLE | 409 | POST /audit/{audit_id}/restore | There is no value to restore, or the revert feature is turned off | — |
RESTORE_BLOCKED | 409 | POST /audit/{audit_id}/restore | Reverting would be inconsistent with the current state. details.kind and details.key identify the blocked target | Resolve it first, using message as a guide |
RESTORE_CONFLICT | 409 | POST /audit/{audit_id}/restore | The same target was changed again after this change. details.conflicts lists them | Revert the later changes first, or overwrite with force: true |
Wallet Callback status
In wallet callbacks the direction is reversed. The platform calls the operator, and the operator returns HTTP 200 with one of the status values below. The platform's handling of each value is described in the wallet callback overview.
| status | Meaning | On debit | On credit / rollback |
|---|---|---|---|
OK | Processed | Confirmed | Confirmed |
INSUFFICIENT_FUNDS | Insufficient balance | Rejected | Retried — do not use |
PLAYER_NOT_FOUND | Player does not exist | Rejected | Retried — do not use |
PLAYER_BLOCKED | Blocked or self-excluded | Rejected | Retried — do not use |
LIMIT_EXCEEDED | Responsible gambling limit exceeded | Rejected | Retried — do not use |
CURRENCY_MISMATCH | Currency mismatch | Rejected | Retried |
INVALID_SIGNATURE | Signature verification failed | Rejected | Retried |
TX_ALREADY_ROLLED_BACK | A debit whose rollback arrived first | Rejected | Retried — do not use |
INVALID_REQUEST | Field error | Rejected | Retried |
UNKNOWN_ERROR | Unknown whether it was processed | Failure + platform rolls back | Retried |
Credits and rollbacks end only with OK. For details on each endpoint, see balance, debit, credit, and rollback.
Wallet-Related Errors on the Player Screen
These are the wallet-related errors players may see on the game screen. Use them as a reference when handling customer inquiries.
| Code | When |
|---|---|
INSUFFICIENT_FUNDS | The operator wallet returned insufficient funds for a debit |
LIMIT_EXCEEDED | The operator wallet returned limit exceeded for a debit |
OPERATOR_CREDIT_EXHAUSTED | In prepaid operating mode, the operator's prepaid credit is insufficient — the wallet is not called |
WALLET_UNAVAILABLE | The debit outcome is uncertain (timeout, connection failure, UNKNOWN_ERROR), other wallet rejections, or a failed balance refresh |