Receive Data from RGS-CWS API - Seamless Wallet

Seamless Wallet Endpoints: getbalance & balance_adj

Essential credentials required to integrate: API Encryption Key, Operator ID
For the Seamless Wallet functionality to work, the RGS-CWS will need to send HTTP POST requests to two URLs provided by your team:

  • getbalance: to retrieve player wallet balance.

  • balance_adj: to update player wallet (bet, win, cancelbet, cancelwin).

These endpoints must follow our security and response guidelines. Be sure to read Security – Trusting Our Data for hash validation setup and other guidelines.

IMPORTANT: Our games will send data to your endpoints, only when the game is opened in “real mode”. “fun mode” will not send any data to your endpoints.

NOTE: It is also important for your code to respond in a short amount of time and avoid timing out. We consider a timed out transaction to be a transaction with a response time >=5 seconds. After this time, the transaction is retried once, right away. If no success, it will be put in a queue and it will be cancelled (cancel request being sent once every 5 minutes - this interval increases and becomes less frequent)


💳 getbalance Endpoint

Used by RGS-CWS to request the current balance of a player from your platform.

RGS-CWS will send a JSON string in a POST request. You must decode and parse it. The structure is as follows:

📜 Sample JSON Request from RGS-CWS to your server - getbalance:

POST /getbalance.php
{
"command":"getbalance",
"userid":"224",
"login":"u241_8841",
"timestamp":"2025-07-02 14:10:00"
}

📥 Input Parameters (coming from RGS-CWS) - getbalance:

Parameter

Always Present

Description

DataType

command

Must be "getbalance"

string

userid

Unique RGS-CWS user ID. You can ignore

string

login

Username from your system, that you originally passed when registering the user or generating the game play token — but it will be prefixed. You must replace ‘u241_’ with ‘‘(nothing) , assuming 241 is your operator id.
In staging, you must replace ‘stg_u241_’ with ‘‘(nothing), assuming 241 is your operator id.

Player username (may include currency suffix in format: username_CURRENCY, e.g., "john_USD". Remove the suffix to get the original username)

string

timestamp

Expiry timestamp (max 15 minutes ahead)

string

currency

Currency code (e.g. USD, GC)

string

internal_session_id

PHP Session ID

string

uniqid

Unique ID of current Request

string

type

This has always the value “getbalance” for this endpoint

string

custom_data

This represents the value of the custom_data string that you initialized when you generated the game token. If you did not set any value, it will be empty.

string

hashed_result

HMAC-SHA256 signature ; key=your api_encryption_key

This is obtained by hashing these variables, in this exact order:

command, timestamp, login, internal_session_id, uniqid, type, userid, custom_data

Sample hashing code:

hash_hmac('sha256', json_encode(array(
$data['command'], 
$data['timestamp'], 
$data['login'],//original login, as we send it 
$data['internal_session_id'], $data['uniqid'], 
$data['type'], 
$data['userid'], $data['custom_data']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $api_encryption_key);

string


IMPORTANT: The login will always contain a prefix.
For production the prefix is ‘u241_’, where 241 is your operator id. This is different for every operator.
For staging the prefix is ‘stg_u241_’, where 241 is your operator id. This is different for every operator.
You must trim this prefix.


IMPORTANT: The login parameter may also contain a currency suffix in the following format: username_CURRENCY
Examples:
- john_USD (user "john" playing with USD)
- player123_EUR (user "player123" playing with EUR)
- testuser_BTC (user "testuser" playing with BTC)

Please remove the currency suffix from the end of the login string. You can find a code snippet below on how to do it properly.
Warning: When writing your code, make sure you do the trimming only at the end to avoid scenarios where the currency code appears in the username itself. For example, if the currency is COINS and the username is joe_coinstar, you should NOT accidentally remove _coins from the middle of the username.

Example
$operatorid = 241; //PRODUCTION $login = str_replace('u'.$operatorid.'_','',$login))); //STAGING if ($request['environment']=='staging'){ $login = str_replace('stg_u'.$operatorid.'_','',$login))); } //REMOVE CURRENCY SUFFIX (only at the end) $suffix = '_'.strtoupper($currency); if (substr($login, -strlen($suffix)) === $suffix) { $login = substr($login, 0, -strlen($suffix)); }

📤 Output Response Format (Expected from your server) - getbalance:

{
  "status": "1",
  "balance": "2221212.44"
}

💸 balance_adj Endpoint

Used by RGS-CWS to notify your system about real-time wallet changes like bets, wins, cancels.

RGS-CWS will send a JSON string in a POST request. You must decode and parse it. The structure is as follows:

📜 Sample JSON Request from RGS-CWS to your server - balance_adj

POST /balance_adj.php
{
  "command": "balance_adj",
  "amount": "-25.0000",//4 decimals precision, sent as string, not float
  "userid": "1441",
  "login": "u241_166273",
  "type": "bet",
  "timestamp": "2025-07-02 14:00:00",
  "gpid": "100",
  "uniqid": "1ee2a1a9c481f330cdb5f701d9c78bef",
  "gameid": "6857",
  "internal_session_id": "abc123",
  "gpid_status": "nt",
  "currency": "USD",
  "subtype": "gamble",
  "is_jackpot_win": "1",
  "hashed_result": "..."
}

📥 Input Parameters (coming from RGS-CWS) - balance_adj:

Parameter

Always present

Description

Data Type

command

Must be "balance_adj"

string

amount

Amount to adjust. Negative = bet, Positive = win. 4 decimal max

string

userid

RGS-CWS internal user ID

string

login

Username from your system, that you originally passed when registering the user or generating the game play token — but it will be prefixed. You must replace ‘u241_’ with ‘‘(nothing) , assuming 241 is your operator id.
In staging, you must replace ‘stg_u241_’ with ‘‘(nothing), assuming 241 is your operator id.

Player username (may include currency suffix in format: username_CURRENCY, e.g., "john_USD". Remove the suffix to get the original username)

string

type

One of: bet, win, cancelbet, cancelwin

string

timestamp

Transaction expiry time (15 min ahead max)

string

gpid

Game play ID (can be repeated across related transactions like freespins)

string

gpid_status

Game round status: nt (incomplete), ok (completed)

string

gameid

Game ID, e.g. 5203

string

internal_session_id

Session identifier from RGS-CWS system. It has no specific purpose.

string

uniqid

Unique transaction ID. Use this to ensure idempotency

string

currency

Currency code (e.g. USD, EUR)

string

subtype

Optional. E.g. gamble

string

is_jackpot_win

If present and set to "1", the win was from a jackpot

string

hashed_result

HMAC-SHA256 signature ; key=your api_encryption_key

This is obtained by hashing these variables, in this exact order:

command, timestamp, login, internal_session_id, uniqid, type, userid, custom_data, amount

Sample PHP hashing code:

hash_hmac('sha256', json_encode(array(
$data['command'], 
$data['timestamp'], 
$data['login'],//original login, as we send it  
$data['internal_session_id'], $data['uniqid'], 
$data['type'], 
$data['userid'], 
$data['custom_data'], $data['amount']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $api_encryption_key);

string

📤 Output Response Format (Expected from your server) - balance_adj:

Your endpoints must return a valid JSON response with the following fields:

Parameter

Required

Description

Type

status

"1" = success, "-1" = reject. Any other value is invalid.

string

balance

New user balance (as a string with decimals). If no update was made, please return the current balance value.

string

txid

Unique transaction ID from your system. Can be a number or alphanumeric.

string

errormsg

Message shown to the player if status is -1.

string

🔴 Important: Returning status: "-1" means the transaction is permanently rejected and will not be retried.


✅ Example for success

{
  "status": "1",
  "balance": "22221212.44",
  "txid": "TX3890021"
}

❌ Example for failure

{ 
"status": "-1", 
"balance": "22221212.44", 
"errormsg": "Insufficient Balance" 
} 

✅ Best Practices

  • Remove prefixes and suffixes from the username

  • Always validate the hashed_result signature

  • Always verify if the user has sufficient funds in his wallet before applying balance adjustments. EG: if (amount<0 && wallet_balance+amount>=0) only then process it and make sure to update your local balance right away. If you use SQL, you can do conditional query and see number of affected rows after your query, to determine if the balance was updated or not UPDATE users SET balance=balance+amount WHERE user=’myusername’ AND balance>=amount. Now count the number of affected rows (must be 1).

  • Log all transactions, even failed ones, for auditability.

  • Optimize your setup by NOT updating the balance when the amount is 0$, but store the transactions for idempotency and gameplay progress tracking

  • Always validate that incoming transactions are not duplicated using the uniqid field. If you processed a transaction in the past, do not process it again.

  • Use a timestamp window (e.g. 15 minutes) to reject expired requests.

  • When receiving a cancelbet or cancelwin, search and reverse the matching original transaction or rely on the amount value that we send to apply to the player balance.
    EG: a bet request like this {"type":"bet","amount":"-25","txid":"891h591gajsoeg"} will have an equivalent cancelbet such as this {"type":"cancelbet","amount":"25","txid":"cancel_891h591gajsoeg"}

  • Always send amounts as numeric strings with 2 to 4 decimal places (e.g., "25.00", "0.1234").

  • Do not reject duplicate transactions silently — always reply with status: 1 if already handled.


🔐 Verifying Signature

If hashed_result is included, verify it using your API secret key. Read more here.

Example
//Sample code to validate the hashed string in the balance_adj endpoint //Sample code to validate the hashed string in the balance_adj endpoint $calculated_hash = hash_hmac('sha256', json_encode(array( $data['command'], $data['timestamp'], $data['login'], $data['internal_session_id'], $data['uniqid'], $data['type'], $data['userid'], $data['custom_data'], $data['amount'], //in getbalance this is not sent so please adjust accordingly ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $api_encryption_key); $sent_hash = $data['hashed_result'] ?? ''; if (!hash_equals($calculated_hash, $sent_hash)) { // ← Changed from $hashed_result to $sent_hash // Invalid signature - reject the request http_response_code(403); echo json_encode(['status' => '-1', 'balance' => '0.00', 'errormsg' => 'Invalid signature']); exit; } // Valid - continue processing
  • Reject request if computed hash does not match hashed_result

  • This improves trust between RGS-CWS and your system


🚫 Insufficient Funds

  • On bet requests, check player's wallet before processing.

  • If balance is not enough:

    • Return status: "-1"

    • Include a proper errormsg so the game client can display it

{ "status": "-1", "balance": "4.00", "errormsg": "Insufficient balance" }

Important: Log rejected transactions for idempotency check


🔁 Idempotency

  • Each transaction comes with a unique uniqid.

  • You must check if the uniqid was already processed by your system (store each uniqid in a database table and perform search queries to see if you already have it processed):

    • If yes, respond with status: "1" and the last known balance.

    • If no, process the transaction normally and store the uniqid. Respond adequately (status:"1")

  • Required to avoid double processing of bets or wins in case of retries.

// Response that your server should return on Duplicate transaction ID
{ "status": "1", "balance": "123.45" }

✖️ Cancel Transactions

RGS-CWS may send cancelbet or cancelwin operations if a transaction expires or is rolled back. You can read more about this in the “Handling Timeouts” documentation section.
This feature is available only on-demand.

Field

Value

Notes

type

"cancelbet" / "cancelwin"

Indicates the reversal of a previous bet or win

uniqid

cancel_123456abcdef

Strip cancel_ and look up original uniqid to revert

Best practice: treat cancel_123456abcdef as a rollback for the transaction with uniqid = 123456abcdef


🔁 Retry Policy

  • If your system does not respond within 5 seconds or returns a malformed response:

    • The same win request will be retried every 5 minutes

    • Bet requests will be cancelled and passed as type=cancelbet

    • Retries will continue until a valid JSON response with status: "1" is received
      Common reasons for retry: Timeout, No response, Missing/invalid status field in JSON

  • Common reasons for retry:

    • Timeout

    • No response

    • Missing/invalid status field in JSON

  • You must ensure that duplicate handling logic is applied via uniqid

  • In the future the retry mechanism may suffer changes and the time interval for repeating will grow exponentially (5 min for #1 attempt, 10 min for #2 attempt, 30, 60, 120, 300, 600, stop)

  • This feature is available only on-demand.

    🛠️ You can optionally set up a cronjob on your server to execute every 5 minutes and to fetch and process missed wins or bets by polling endpoints described in E27/E28 of the original documentation. You can read more about this in the Handling Timeouts documentation section.