Integration Checklist
Items for the operator to verify before go-live. During certification, we check them together using this list.
Signing and security
- [ ] All 3 test vectors (POST, GET with an encoded query, wallet debit) match the expected signatures.
- [ ] The API secret is used as the key as the 64-character string, as is, without hex-decoding.
- [ ] The signed body bytes are identical to the body bytes actually sent (no double serialization).
- [ ] Query values are percent-encoded (
+→%2B), and that exact string is signed. - [ ]
X-Api-Keyis included on every Operator API request. - [ ] A new timestamp, nonce, and signature are generated on retries.
- [ ] The operator server clock is synchronized with NTP (tolerance ±5 minutes).
- [ ] The API key and API secret exist only in the server configuration and never appear in browser code, apps, repositories, or logs.
- [ ] The public IPs of all servers that call the Operator API are registered in the IP allowlist.
- [ ] The wallet URL uses HTTPS, and the firewall allows the platform's outbound IPs for wallet callbacks.
- [ ] Switched to the production credentials, base URL, and game screen origin (no test values remain).
Wallet callbacks — common
- [ ] Callback signatures are verified with the raw body bytes, and
X-Operator, the timestamp (±5 minutes), and a constant-time comparison are all checked. - [ ] Callback nonces are kept for at least 5 minutes in storage shared by all servers, and reuse is rejected.
- [ ] Even if a reverse proxy rewrites the path, the signature is verified using the original path of the registered wallet URL.
- [ ] All business outcomes, including rejections, are returned as HTTP 200 + a
statusin the body. - [ ] The response
balanceis the balance after processing, as an integer in the currency's minor unit. - [ ]
tx_ididempotency: when an already processedtx_idarrives again, the balance is not changed again and the same response as the first time is returned (the same rejection if it was rejected). - [ ] Concurrent processing of transactions for the same player does not corrupt the balance (DB transactions, row locks).
- [ ] Response times are short enough — the platform waits 3 seconds for
balanceanddebit, and 5 seconds forcreditandrollback. - [ ] The wallet ledger records
tx_id,round_id,reason,amount, and the processing result so that reconciliation is possible.
balance
- [ ] Responds with
PLAYER_NOT_FOUNDfor a nonexistent player andCURRENCY_MISMATCHwhen the currency differs.
debit
- [ ] If the balance is insufficient, nothing is deducted and
INSUFFICIENT_FUNDSis returned. - [ ] Players who are blocked or self-excluded are rejected with
PLAYER_BLOCKED. - [ ] If a debit arrives late for a
tx_idwhose rollback has already arrived, nothing is deducted andTX_ALREADY_ROLLED_BACKis returned. - [ ] The implementation assumes that when a debit ends in a timeout, an HTTP error, or
UNKNOWN_ERROR, the platform does not retry the debit and sends a rollback immediately. - [ ] The
reason(bet,ante,double,split,buy_in,top_up) is recorded in the ledger.
credit
- [ ] A credit with amount
0(settlement of a lost round) is processed normally andOKis returned. - [ ] Credits are applied even to blocked players (wins and cash-outs from a game in progress).
- [ ] You understand that a credit is retried indefinitely unless it returns
OK, regardless of status, and you never return a status other thanOKfor a valid transaction. - [ ] Even if the same
tx_idrepeats at the retry intervals (1s → 2s → 5s → 15s → 1 min → 5 min, then every 5 minutes), it is applied only once.
rollback
- [ ] The original debit is looked up by
ref_tx_id. - [ ] If the original debit succeeded, its amount is reversed and
OKis returned. - [ ] If there is no record of the original debit (the debit never arrived), nothing is reversed and
OKis returned, and thatref_tx_idis recorded so that a late-arriving debit is rejected. - [ ] If the original debit was already reversed or was rejected, it is not reversed again and
OKis returned. - [ ] The implementation assumes that a rollback is also retried indefinitely unless it returns
OK. - [ ] The
reason(cancel_bet,round_void,timeout,system) is recorded in the ledger.
Failure scenarios
During certification, it is useful to deliberately inject failures into a test wallet and verify the following.
- [ ] Delay the debit response by more than 3 seconds → the bet or seating fails, a rollback (
timeout) arrives, and the balance returns to its original value. - [ ] Return HTTP 500 for a debit → same as above.
- [ ] Return HTTP 500 for a credit a few times and then respond normally → through retries it is ultimately applied exactly once.
- [ ] Sending the same
tx_idtwice changes the balance only once. - [ ] Even if the wallet server goes down briefly and comes back up, all pending credits and rollbacks are applied after it recovers.
Game launch
- [ ]
POST /launchis called only from the operator server. - [ ] A new
launch_urlis obtained every time the player clicks (60 seconds, single use) and opened exactly as received. - [ ] A new window is opened directly inside the click handler, and
noopeneris not used. - [ ] If embedding in an iframe, the embed domain is registered and the iframe is closed when
game.closedis received. - [ ] A
return_urlis sent or a default return URL is registered (without either, no postMessage messages are sent). - [ ] When receiving postMessage messages,
event.originanddata.source === "games-platform"are checked. - [ ]
external_idis a value that never changes for a given player and is 64 bytes or less. - [ ]
nicknameis sent within 2–16 characters. - [ ] The fact that a player's currency is fixed (
CURRENCY_MISMATCH) is taken into account. - [ ]
operator_session_iduses an opaque ID rather than the raw login token. - [ ] Launch errors such as
PLAYER_BLOCKED,GAME_MAINTENANCE, andTABLE_NOT_FOUNDare communicated appropriately to the player.
Player management
- [ ]
POST /players/{external_id}/logoutis called on site logout, self-exclusion, and account suspension (block: truefor suspension). - [ ] When lifting a suspension, it is called again with
block: false.
Reconciliation and operations
- [ ] Wallet transactions for a period are fetched with
GET /transactionsand matched against your own wallet ledger pertx_id(a scheduled job). - [ ] Transactions in
pendinganduncertainstatus are reviewed separately during reconciliation. - [ ] If you need a bet history screen, use
GET /roundsandGET /rounds/{round_id}. - [ ] Under
prepaidoperation, the prepaid credit balance is monitored withGET /credit, and a top-up is requested before it drops below the warning threshold (warn_below). - [ ] Operator API
429and5xxresponses are retried after a wait (for write requests, check the result first). - [ ] The contact person and channel for outages and reconciliation mismatches have been decided.