Reference
Error codes
Every error code the API returns, its status, and whether retrying can help.
Every code the API returns, what it means, and whether retrying can help. The envelope is described in Errors.
iRetryable is a field, not a guess
Each error carries
retryable. Only five codes ever set it true — WALLET_TIMEOUT, WALLET_UNAVAILABLE, RATE_LIMITED, SERVICE_UNAVAILABLE and INTERNAL_ERROR — and they are marked below. Branch on the field rather than on the status: a 409 is never worth repeating, and a 504 always is, with the same transaction_id.Authentication and access
UNAUTHORIZED401 · no retry | Missing or malformed Authorization header. |
INVALID_CREDENTIALS401 · no retry | The key and secret pair did not match, or the token failed verification. |
TOKEN_EXPIRED401 · no retry | Mint a fresh token and repeat the request. Not marked retryable because the identical request would fail again — you must get a new token first. |
INVALID_SIGNATURE401 · no retry | An HMAC signature you sent us did not verify. |
IP_NOT_ALLOWED403 · no retry | Source address outside the credential’s allowlist. |
FORBIDDEN403 · no retry | Authenticated, but not permitted — your role, or a capability your plan does not include. The message names the plan that would allow it. |
INSUFFICIENT_SCOPE403 · no retry | The token is valid but was minted for another audience — a launch token used against the operator API, say. See token audiences. |
Account state
OPERATOR_SUSPENDED403 · no retry | The account is suspended. Contact support. |
OPERATOR_NOT_LIVE403 · no retry | A live-only operation on an account whose real-money play is suspended. |
REAL_MONEY_DISABLED403 · no retry | Real-money play is switched off — either platform-wide, or suspended on your account. The message says which; only one of them is something you can act on. |
BRAND_NOT_FOUND404 · no retry | No such brand on this account. |
PLAYER_BLOCKED403 · no retry | Your own wallet refused the player — self-exclusion, a KYC hold, or an unknown player id. |
Validation
VALIDATION_ERROR422 · no retry | A field is missing or the wrong shape. Carries details naming each offending path — a JSON number where a decimal string was required is the usual cause. |
CURRENCY_NOT_SUPPORTED422 · no retry | The currency is not enabled for your account. Games do not restrict currencies — add it with PATCH /v1/business and the next session opens. |
CURRENCY_MISMATCH422 · no retry | The movement currency differs from the session currency. |
Money
INSUFFICIENT_FUNDS402 · no retry | Your wallet refused: balance below the stake. Nothing moved. |
BET_LIMIT_EXCEEDED422 · no retry | Stake outside the min/max configured for the game on your account. |
TRANSACTION_CONFLICT409 · no retry | The same transaction_id arrived again with a different body. Fix the caller; nothing moved. Retrying can only conflict again. |
TRANSACTION_NOT_FOUND404 · no retry | No movement with that id on this account — including a reference_transaction_id on a refund or rollback that names nothing. |
TRANSACTION_ALREADY_REVERSED409 · no retry | The original movement has already been refunded or rolled back. |
Your wallet
These describe your wallet’s behaviour, not ours. See wallet integration.
WALLET_TIMEOUT504 · retry | Your wallet did not answer in time. The transaction is left pending and the outcome is genuinely unknown — retry with the same transaction_id. |
WALLET_UNAVAILABLE503 · retry | We could not reach your wallet at all. Same treatment as a timeout. |
WALLET_REJECTED502 · no retry | Your wallet refused with a code we do not recognise, or one that is terminal. The raw code is preserved on the transaction record. |
WALLET_NOT_CONFIGURED503 · no retry | No active wallet integration for this environment. Most often a live key against an account that has only configured a sandbox wallet — the two are separate records and one never falls back to the other. |
Games, sessions and rounds
GAME_NOT_FOUND404 · no retry | No such game, or it is not in your catalogue at all. |
GAME_NOT_ENABLED403 · no retry | The game is in your catalogue but switched off for you. |
GAME_UNAVAILABLE503 · no retry | The game exists and is enabled, but is down platform-wide right now. |
SESSION_NOT_FOUND404 · no retry | Unknown session, or it belongs to another operator. |
SESSION_EXPIRED410 · no retry | The session passed its expiry. Create a new one. |
SESSION_CLOSED410 · no retry | The sitting has ended. |
ROUND_NOT_FOUND404 · no retry | Unknown round id. |
ROUND_IN_PROGRESS409 · no retry | One open round per player per game — a round open in one game never blocks another. If it will not clear, the round was opened but its stake never taken; void it with POST /v1/rounds/{roundId}/void. |
ROUND_ALREADY_SETTLED409 · no retry | The round has already reached a terminal state; no further action is possible. |
Platform
RATE_LIMITED429 · retry | Too many requests. Honour Retry-After and add jitter. See rate limits. |
NOT_FOUND404 · no retry | No route, or a resource outside your account. We do not distinguish the two — see below. |
CONFLICT409 · no retry | The resource already exists. |
INTERNAL_ERROR500 · retry | Our fault. Retry; quote the request id if it persists. |
SERVICE_UNAVAILABLE503 · retry | Briefly unable to serve, or shedding load under saturation — see rate limits. Always retryable. Settlement is never shed. |
·404 rather than 403 for another operator’s data
Asking for a session, round or transaction that belongs to someone else returns
NOT_FOUND, not FORBIDDEN. Answering “forbidden” would confirm the resource exists, which leaks the shape of other tenants’ data to anyone willing to enumerate ids. Absence and denial look identical from outside.