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:
IMPORTANT: The
loginwill 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: Theloginparameter 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 isCOINSand the username isjoe_coinstar, you should NOT accidentally remove_coinsfrom 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:
📤 Output Response Format (Expected from your server) - balance_adj:
Your endpoints must return a valid JSON response with the following fields:
🔴 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
uniqidfield. 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
cancelbetorcancelwin, 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: 1if 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 processingReject request if computed hash does not match
hashed_resultThis 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
errormsgso 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
uniqidwas 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.
Best practice: treat
cancel_123456abcdefas a rollback for the transaction withuniqid = 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=cancelbetRetries 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
statusfield in JSON
You must ensure that duplicate handling logic is applied via
uniqidIn 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.