Codrez RGS
B2B Integration
The Codrez Remote Gaming Server (RGS) provides casino game infrastructure for B2B operators. This documentation covers everything you need for a complete, certified integration.
Secure Authentication
API Key + HMAC-SHA256 on every callback
Seamless Wallet
Your balance, your players — total control
Multi-game
Growing catalog with configurable RTP and volatility
Integration Flow
Authentication
All requests to the RGS must include the header with your API Key. Credentials are available in the Admin Panel after your account is created.
Your credentials
Example of how the header is used across all calls:
curl https://rgs.codrez.com/rgs/v1/games \
-H "X-Codrez-API-Key: ck_your_api_key_here"Environments
Use the Sandbox environment for development and testing. Credentials differ per environment.
https://rgs-sandbox.codrez.comTesting — no real transactions
https://rgs.codrez.comLive — real transactions
List Games
Returns all games available for your operator, filtered by the games enabled by Codrez on your account.
curl -X GET https://rgs.codrez.com/rgs/v1/games \
-H "X-Codrez-API-Key: ck_your_api_key_here"{
"success": true,
"games": [
{
"id": "game_001",
"name": "Spirit of Jungle",
"slug": "spirit-of-jungle",
"provider": "Codrez",
"category": "slot",
"rtp_nominal": 96.5,
"volatility": "high",
"bet_min": 100,
"bet_max": 50000,
"bet_options": [100, 200, 500, 1000, 2000, 5000],
"lines": 20,
"jackpot_enabled": false,
"allow_demo": true,
"thumbnail_url": "https://cdn.codrez.com/games/spirit-of-jungle/thumb.webp"
}
]
}Start Player Session
To start a game session, generate a temporary playerToken on your platform and redirect the player to the RGS launch URL. The RGS uses this token to authenticate the player via callback.
| Parameter | Type | Description |
|---|---|---|
gameSlug* | string | Game slug (obtained from /games) |
playerToken* | string | Short-lived token generated by your platform for the player |
currency* | string | Session currency. E.g.: BRL, USD |
lang | string | Interface language. E.g.: en, es, pt |
curl -G "https://rgs.codrez.com/rgs/v1/launch" \
-H "X-Codrez-API-Key: ck_your_api_key_here" \
--data-urlencode "gameSlug=spirit-of-jungle" \
--data-urlencode "playerToken=PLAYER_TOKEN" \
--data-urlencode "currency=BRL" \
--data-urlencode "lang=en"HMAC Signature
All callbacks sent by Codrez to your server are signed with HMAC-SHA256 using your Callback Secret. Always validate the signature before processing any transaction.
Headers sent with every callback:
X-Codrez-TimestampUnix timestamp (seconds) at send timeX-Codrez-Signaturet={timestamp},s={hmac_sha256_hex}X-Codrez-OperatorOperator slug (for identification)// Signature formula
HMAC-SHA256(
key = callback_secret,
input = "{timestamp}:{raw_json_body}"
)
const crypto = require('crypto');
function verifySignature(rawBody, headers, callbackSecret) {
const timestamp = headers['x-codrez-timestamp'];
const sigHeader = headers['x-codrez-signature'];
const match = sigHeader.match(/s=([a-f0-9]+)/);
if (!timestamp || !match) return false;
const expected = crypto
.createHmac('sha256', callbackSecret)
.update(`${timestamp}:${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(match[1])
);
}Callback: Authenticate
Called by Codrez when a player starts a session. Validate the playerToken and return the player's ID and balance.
Request Body
| Parameter | Type | Description |
|---|---|---|
playerToken* | string | Token generated by your platform |
sessionId* | string | Session ID generated by the RGS |
Expected Response
| Parameter | Type | Description |
|---|---|---|
playerId* | string | Unique player ID in your platform |
balance* | integer | Current balance in cents |
currency* | string | Currency. E.g.: BRL |
app.post('/authenticate', async (req, res) => {
const { playerToken, sessionId } = req.body;
// 1. Verify HMAC signature (see HMAC section)
const player = await db.findByToken(playerToken);
if (!player) return res.status(401).json({ code: 'INVALID_TOKEN' });
return res.json({ playerId: player.id, balance: player.balanceCents, currency: 'BRL' });
});{
"playerId": "player_12345",
"balance": 125000,
"currency": "BRL"
}Callback: Balance
Called to retrieve the player's current balance during the session.
Request Body
| Parameter | Type | Description |
|---|---|---|
playerId* | string | Player ID |
currency* | string | Session currency |
sessionId* | string | Session ID |
Response
| Parameter | Type | Description |
|---|---|---|
balance* | integer | Current balance in cents |
currency* | string | Currency |
app.post('/balance', async (req, res) => {
const { playerId, currency, sessionId } = req.body;
const player = await db.findById(playerId);
if (!player) return res.status(404).json({ code: 'PLAYER_NOT_FOUND' });
return res.json({ balance: player.balanceCents, currency: player.currency });
});{
"balance": 125000,
"currency": "BRL"
}Callback: Debit
Called to debit the player's wager. Idempotency is required — use the idempotencyKey to catch duplicates.
| Parameter | Type | Description |
|---|---|---|
playerId* | string | Player ID |
amountCents* | integer | Bet amount in cents |
currency* | string | Currency |
roundId* | string | Unique round ID |
gameSlug* | string | Game slug |
sessionId* | string | Session ID |
idempotencyKey* | string | Unique idempotency key. Format: {roundId}:debit |
app.post('/debit', async (req, res) => {
const { playerId, amountCents, roundId, idempotencyKey } = req.body;
// Idempotency: if already processed, return saved result
const existing = await db.findTxByKey(idempotencyKey);
if (existing) return res.json({ balance: existing.balanceAfter, transactionId: existing.id });
const player = await db.findById(playerId);
if (player.balanceCents < amountCents) return res.status(402).json({ code: 'INSUFFICIENT_FUNDS' });
const tx = await db.debit({ playerId, amountCents, roundId, idempotencyKey });
return res.json({ balance: tx.balanceAfter, transactionId: tx.id });
});{
"balance": 120000,
"transactionId": "tx_a1b2c3d4"
}Callback: Credit
Called after the round result to credit winnings to the player. amountCents may be 0 if the player did not win.
| Parameter | Type | Description |
|---|---|---|
playerId* | string | Player ID |
amountCents* | integer | Winnings in cents (0 if no win) |
currency* | string | Currency |
roundId* | string | Round ID (same as debit) |
gameSlug* | string | Game slug |
sessionId* | string | Session ID |
idempotencyKey* | string | Format: {roundId}:credit |
app.post('/credit', async (req, res) => {
const { playerId, amountCents, roundId, idempotencyKey } = req.body;
const existing = await db.findTxByKey(idempotencyKey);
if (existing) return res.json({ balance: existing.balanceAfter, transactionId: existing.id });
// amountCents can be 0 (no win)
const tx = await db.credit({ playerId, amountCents, roundId, idempotencyKey });
return res.json({ balance: tx.balanceAfter, transactionId: tx.id });
});{
"balance": 135000,
"transactionId": "tx_f6g7h8i9"
}Callback: Rollback
Called when a round fails after the debit was confirmed. Roll back the debit and restore the player's balance.
| Parameter | Type | Description |
|---|---|---|
playerId* | string | Player ID |
currency* | string | Currency |
roundId* | string | Round ID to roll back |
gameSlug* | string | Game slug |
sessionId* | string | Session ID |
idempotencyKey* | string | Format: {roundId}:rollback |
reason | string | Rollback reason. E.g.: TIMEOUT, GAME_ERROR |
app.post('/rollback', async (req, res) => {
const { playerId, roundId, idempotencyKey } = req.body;
const existing = await db.findTxByKey(idempotencyKey);
if (existing) return res.json({ balance: existing.balanceAfter });
const original = await db.findTxByKey(`${roundId}:debit`);
if (!original) {
const player = await db.findById(playerId);
return res.json({ balance: player.balanceCents });
}
const tx = await db.rollback({ playerId, roundId, idempotencyKey, amountCents: original.amountCents });
return res.json({ balance: tx.balanceAfter });
});{
"balance": 125000
}Error Codes
Use these codes in your callback responses to communicate errors to the RGS in a standardized way.
| HTTP | Code | Description |
|---|---|---|
| 200 | OK | Success |
| 401 | INVALID_TOKEN | playerToken is invalid or expired |
| 401 | INVALID_SIGNATURE | HMAC signature is invalid |
| 402 | INSUFFICIENT_FUNDS | Insufficient balance for the debit |
| 404 | PLAYER_NOT_FOUND | Player not found |
| 409 | TRANSACTION_DUPLICATE | Duplicate transaction (outside idempotency) |
| 422 | INVALID_CURRENCY | Currency not supported by the operator |
| 500 | INTERNAL_ERROR | Internal error on the operator's server |
| 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable |
Standard error format
{
"code": "INSUFFICIENT_FUNDS",
"message": "..."
}