Data format
The conventions every request and response follows.
- JSON,
Content-Type: application/json, UTF-8. Field names are snake_case. - Responses are flat, without an envelope. A success and an error are both top-level objects.
- Currencies are ISO 4217 codes. A session is one currency from open to close; nothing is converted.
- Timestamps are ISO 8601 in UTC:
2026-09-29T12:00:00Z. - Ids are opaque strings up to 120 characters.
player_idis your reference and is never interpreted. - Ignore fields you do not know. New fields are added without a version change.
- A body that is not valid JSON, or a field or query parameter of the wrong JSON type, is refused like any other invalid request: HTTP 422,
VALIDATION_FAILED, with the field named infields(bodywhen the JSON does not parse).
Money
Amounts that move money are decimal strings: "1.50", never 1.5. Decimal point, no thousands separator, in the currency's own precision. Send back what you were sent and do not reformat it.
| Where | JSON type | Fields |
|---|---|---|
| Wallet callbacks and answers | string | amount, balance, bonus_amount |
| Transactions and rounds | string | amount |
| Free spins | string | bet_amount, win_amount, bet-option amounts |
| Jackpots | number | tiers[].amount, winners amount |
| Rates | number | percent, from_amount, to_amount |
| Invoice webhook | number | every figure: revenue, total, amount, tax_amount… |
Your wallet must answer balance as a string. A numeric balance cannot be read, and an unreadable answer is treated as no answer: the call is retried and then rolled back.
Game identifiers
A game has two identities, and they travel in different places.
| Field | Where | What it is |
|---|---|---|
| id | catalogue (GET /v1/games) | Our id of the title (UUID). It is what you send as game_id to POST /v1/sessions, free spins and demo. |
| code | catalogue | The provider game code, for display and support. |
| provider_code | catalogue | The provider, as GET /v1/providers names it. |
| game_id | wallet callbacks | The game provider's code for the round being played, e.g. vs20fruitsw. It is not the catalogue id, and can differ from code. |
| game_ids | free-spin grant answer | Game provider codes, as the series was placed. |
Mapping a wallet callback to the catalogue
GET /v1/games → game.id = "6ddd5f30-0b1c-4c52-9f3e-2a7c1b8e4d10"
POST /v1/sessions { game_id: game.id }
→ session_id = "2222aaaa-…" store (session_id → game.id)
wallet call { session_id: "2222aaaa-…", game_id: "vs20fruitsw" }
→ look up session_id → game.idKey your records by session_id. It is on every wallet callback and maps back to the catalogue game ID you launched.
Rate limits
Limits are configured per operator as requests per calendar minute and are given to you with your credentials. The window restarts at the start of each minute and counts only correctly signed requests.
- Over the limit: HTTP 429,
RATE_LIMITED,retryable: true. - The answer carries
Retry-After: whole seconds until the next minute starts, from 1 to 60. Wait that long, then retry with the same ids. - Fetch the catalogue, providers and rates on a schedule and cache them; they change when providers publish, not per player.
