Wallet Callbacks

When a player launches a game or places a bet, the RGS calls your backend to authenticate the player, debit, or credit the player's balance. You must implement these five endpoints at the callback URL registered during onboarding.

All callbacks are POST requests with a JSON body, signed with HMAC-SHA256 via X-Timestamp and X-HMAC-SHA256 headers. See Authentication for verification details.

Currencies & Amounts

Amounts in all callbacks are represented as decimal strings (e.g., "1.50") to avoid floating-point precision issues. Use GET /operator/currencies to fetch the current list of supported currency codes.

RMB is accepted as an alias for CNY. If you need a currency not listed, contact us during onboarding.

Authenticate

POST /callback/authenticate — Verify the player and return their balance when a session is launched.

The RGS calls this endpoint during POST /operator/launch to confirm that the player exists and is allowed to play.

Request Fields

Field Type Required Description
requestId string Yes Unique identifier for this request
playerId string Yes The player ID provided in the launch request
currency string Yes Currency code for the session (e.g., "USD")
gameCode string Yes Game code being launched (e.g., "dice-alpha")
{
  "requestId": "unique-request-id",
  "playerId": "player-1",
  "currency": "USD",
  "gameCode": "dice-alpha"
}

Response Fields

Field Type Required Description
requestId string Yes Echo back the requestId from the request
status string Yes "OK" on success, or an error code
balance string Yes (if OK) Player's current balance as a decimal string (e.g., "100.00")
accountCurrency string No Player's wallet currency — must match the request currency if provided
name string No Player's display name
countryCode string No Player's country (ISO 3166-1 alpha-2)
languageCode string No Player's language preference (ISO 639-1)
birthDate string No Player's date of birth (YYYY-MM-DD)
registrationDate string No When the player registered (YYYY-MM-DD)
address string No Player's address
{
  "requestId": "unique-request-id",
  "status": "OK",
  "balance": "100.00",
  "accountCurrency": "USD",
  "name": "John Doe",
  "countryCode": "US",
  "languageCode": "en",
  "birthDate": "1990-01-01",
  "registrationDate": "2024-01-15",
  "address": "123 Main St"
}

If accountCurrency is provided, it must match the currency sent in the request. A mismatch will cause the launch to fail.

Debit

POST /callback/debit — Deduct the bet amount from the player's balance.

Request Fields

Field Type Required Description
requestId string Yes Unique identifier for this request
playerId string Yes The player placing the bet
transactionId string Yes Unique transaction ID — use as idempotency key
roundId string Yes The game round this debit belongs to
gameCode string Yes Game code (e.g., "dice-alpha")
amount string Yes Bet amount as a decimal string (e.g., "1.50")
metadata string No JSON string with extra transaction details
{
  "requestId": "unique-request-id",
  "playerId": "player-1",
  "transactionId": "unique-transaction-id",
  "roundId": "round-uuid",
  "gameCode": "dice-alpha",
  "amount": "1.50",
  "metadata": "{}"
}

Response Fields

Field Type Required Description
requestId string Yes Echo back the requestId from the request
status string Yes "OK" on success, or an error code
balance string Yes (if OK) Player's balance after the debit
customUserError string No Message displayed to the player when the debit is rejected
{
  "requestId": "unique-request-id",
  "status": "OK",
  "balance": "98.50"
}

Credit

POST /callback/credit — Credit the player's balance with winnings.

The RGS always sends a credit callback, even when the player loses — the amount will be "0". A round is always closed by either a credit or a rollback, never by a debit alone. Check roundClosed to determine if the round has ended.

A credit with amount: "0" and roundClosed: true signals the round ended with no payout. Always respond with OK and the current balance.

Request Fields

Field Type Required Description
requestId string Yes Unique identifier for this request
playerId string Yes The player receiving the credit
transactionId string Yes Unique transaction ID — use as idempotency key
roundId string Yes The game round this credit belongs to
roundClosed boolean Yes true if this credit closes the round
gameId string Yes Game code (e.g., "dice-alpha")
amount string Yes Payout amount as a decimal string — "0" for losses
metadata string No JSON string with extra transaction details
{
  "requestId": "unique-request-id",
  "playerId": "player-1",
  "transactionId": "unique-transaction-id",
  "roundId": "round-uuid",
  "roundClosed": true,
  "gameId": "dice-alpha",
  "amount": "3.00",
  "metadata": "{}"
}

Response Fields

Field Type Required Description
requestId string Yes Echo back the requestId from the request
status string Yes "OK" on success, or an error code
balance string Yes (if OK) Player's balance after the credit
{
  "requestId": "unique-request-id",
  "status": "OK",
  "balance": "101.50"
}

sessionToken is not included in credit callbacks — payouts must succeed even after session expiry.

Balance

POST /callback/balance — Return the player's current balance (e.g., when loading the game UI).

Request Fields

Field Type Required Description
requestId string Yes Unique identifier for this request
playerId string Yes The player whose balance to return
{
  "requestId": "unique-request-id",
  "playerId": "player-1"
}

Response Fields

Field Type Required Description
requestId string Yes Echo back the requestId from the request
status string Yes "OK" on success, or an error code
balance string Yes (if OK) Player's current balance
{
  "requestId": "unique-request-id",
  "status": "OK",
  "balance": "100.00"
}

Rollback

POST /callback/rollback — Reverse a previously placed bet. The RGS sends this when a debit callback fails (500 response, timeout, etc.) to ensure the player doesn't lose money if the debit was applied on your side. The reverseTransactionId identifies which debit transaction to reverse.

Your server must handle rollbacks that arrive before the corresponding debit — or for debits your server never acknowledged. If a debit call times out from the RGS side, the RGS may issue a rollback even though your server never confirmed the debit. Treat a rollback for an unknown reverseTransactionId as successful (return OK) since the original debit was never applied.

Request Fields

Field Type Required Description
requestId string Yes Unique identifier for this request
playerId string Yes The player whose bet is being reversed
transactionId string Yes Unique transaction ID for this rollback — use as idempotency key
reverseTransactionId string Yes The transactionId of the original debit being reversed
roundId string Yes The game round this rollback belongs to
roundClosed boolean Yes true if this rollback closes the round
gameId string Yes Game code (e.g., "dice-alpha")
metadata string No JSON string with extra transaction details
{
  "requestId": "unique-request-id",
  "playerId": "player-1",
  "transactionId": "rollback-transaction-id",
  "reverseTransactionId": "original-bet-transaction-id",
  "roundId": "round-uuid",
  "roundClosed": true,
  "gameId": "dice-alpha",
  "metadata": "{}"
}

Response Fields

Field Type Required Description
requestId string Yes Echo back the requestId from the request
status string Yes "OK" on success, or an error code
balance string Yes (if OK) Player's balance after the rollback
{
  "requestId": "unique-request-id",
  "status": "OK",
  "balance": "100.00"
}

sessionToken is not included in rollback callbacks — reversals must succeed even after session expiry.

Response Status Codes

All callback responses must include a status field. Return "OK" on success, or one of these error codes:

Status Meaning
OK Success
ERROR_NOT_ENOUGH_MONEY Insufficient funds to place the bet
ERROR_PLAYER_DISABLED Player account is locked or disabled
ERROR_INVALID_SESSION Session token is unknown
ERROR_SESSION_EXPIRED Session has expired
ERROR_INVALID_GAME Game is unknown or disabled
ERROR_WRONG_CURRENCY Currency mismatch with player's wallet
ERROR_DUPLICATE_TRANSACTION transactionId already processed with different parameters
ERROR_TRANSACTION_DOES_NOT_EXIST Rollback target bet was never processed (treat as success)
ERROR_INVALID_SIGNATURE HMAC verification failed
ERROR_WRONG_SYNTAX Malformed request
ERROR_UNKNOWN Any other error

Idempotency

Every /callback/debit, /callback/credit, and /callback/rollback request includes a unique transactionId. Your server should use this as an idempotency key — if you receive a request with a transactionId you've already processed, return the same successful response without applying the transaction again.

The RGS retries callbacks on transient failures (timeouts, 5xx responses). Each retry sends the same transactionId, so deduplication ensures transactions are only applied once.

Currently all games produce one debit and one credit per round. Future games may produce additional debit/credit pairs within a single round, so your callback implementation should support multiple transactions per roundId.