Skip to content

Errors & retry

Two independent error surfaces exist in this integration, and it matters which one you're debugging:

  • Operator API errors — the platform's response to a call you made (launch, games, kick, rounds/replay, free spins).
  • Wallet callback errors — how the platform interprets your response when it calls your POST /v1/wallet/transaction or GET /v1/wallet/balance.

Signature & replay errors (shared by both directions)

These apply identically whether you're the one being verified (Operator API) or the platform is (wallet callback) — see Signing & authentication.

StatusMeaningBody
401Bad, missing, or expired-timestamp signaturePlain text: invalid signature — not JSON, since this check happens before the request reaches any handler
401A nonce that's already been used (replay)JSON { "error": "replayed request" }
400Missing or oversized X-NonceJSON { "error": "invalid nonce" }

Operator API status codes

Every endpoint in the Operator API reference shares this shape. Business errors (game not found, currency not supported, etc.) are JSON { "error": "<message>" }.

StatusMeaning
400Invalid request body, or a value doesn't validate (unsupported currency/language, missing required field)
401No operator identity resolved — see the signature errors above
403The launch was blocked by risk control (player blocklist / self-exclusion) — see POST /v1/operator/games/launch
404The game doesn't exist, or exists but isn't visible to your operator tenant (deliberately indistinguishable, so this can't be used to probe the catalog); or, for round replay, no matching round under your tenant
429Rate limit exceeded for your tenant — see Rate limits below
500Unexpected platform-side failure

Rate limits

Every operator API call is rate-limited per tenant. Exceeding it returns:

429
Retry-After: <seconds>
json
{ "error": "rate limit exceeded" }

Back off and retry after the number of seconds in Retry-After rather than retrying immediately. If your expected traffic needs a higher limit than your default, raise it with your integration contact before you hit this in production.

Wallet callback: what the platform does with your response

You don't retry calls to the platform here — the platform is calling you, and interprets whatever you return:

Your responsePlatform's interpretation
200, { status: 'OK', balance }Applied successfully
200, { status: 'DECLINED', balance }BET onlyNormal business decline (e.g. insufficient funds); not retried
200, { status: 'DECLINED' } on WIN/ROLLBACK/ADJUSTMENTInvalid — these types must not decline; treat a real failure as a non-200 instead
Any non-200 statusTreated as a failure. The platform may retry with the exact same transactionId — see Idempotency
No response within your configured timeoutTIMED_OUT — retried or resolved later via reconciliation, same as a non-200

Because a retry reuses the identical transactionId, the single most important thing your implementation does is answer a repeat request with the same cached response, not re-apply the balance change — see Idempotency in the wallet callback API reference.

Idempotency and retries

Every retry — of a call you make, or a call the platform makes to you — reuses the exact same transactionId (or, for free spins, requestRef/idempotencyKey). That shared ID is what lets either side tell "the same logical attempt, retried" apart from "a new attempt." Whichever side is receiving the retry is responsible for deduplicating on it; neither side invents a new ID for a retry of the same attempt.