RGS Math Servers
The RGS (Remote Game Server) and its associated Math Server are the backend engines that determine game outcomes. Every bet, every win, every multiplier — they all come from the math server. Your game client never decides outcomes; it receives them and renders the result.
Architecture
How it works:
- The Proxy Server authenticates the player through GammaStack (Rollerz) and receives a token, user ID, and balance.
- The Game Client sends its internal client code (game ID) to the proxy and receives back a session ID and the math server endpoint.
- The game client communicates directly with the Math Server using the session ID — opening games, placing bets, and collecting winnings.
- The RGS sits between the proxy and math server, handling session management, wallet operations, and round finalization.
The SDK abstracts all of this behind simple methods like openGame(), placeBet(), and collect(). As a game developer, you call these methods and receive structured results — you never need to manage sessions, request counters, or raw HTTP calls yourself.
Launch URL parameters
When a host platform (e.g. Rollerz) launches your game inside an iframe, it appends two URL parameters that the SDK reads automatically — your code never touches URLSearchParams:
| Parameter | Purpose | Fallback when absent |
|---|---|---|
?server= | Math server URL for this launch — overrides the provider's server-side default | The provider's env-configured server URL (GO3_SERVER_URL, STEPPER_SERVER_URL, etc.) |
?session= | Session token issued by Reelsoft for this player | A UUID minted by the SDK and persisted in sessionStorage — survives refreshes of the same tab; reset on a new tab or closed/reopened browser |
Both values ride in the open request body. The SDK Server passes body.sessionId to the math server's opengame call (and prefers body.serverUrl over the env default for outbound routing). It then stores both on the session record on first contact and reuses them for every subsequent placebet / nextaction / collect — your game code never sends them again.
For GP specifically, the launch URL wins over any explicit openGame({ serverUrl }) argument — host-driven launches always trump in-code defaults.
Host-driven ?server= is allowlist-gated
Because ?server= reaches the SDK server through a request body rather than a vetted env var, outbound POSTs are gated on MATH_SERVER_ALLOWED_HOSTS (comma-separated host[:port] list). Unset = passthrough (local dev only); production deployments must set it to the trusted math-server hosts. Requests to any other host throw disallowed math-server host: <host>. Redirects are refused (redirect: 'error') so a 302 can't laundry the check.
RGS API contract
All communication with the math server uses HTTPS POST with JSON request/response bodies. The SDK handles this for you, but understanding the contract is useful for building mocks or debugging.
The /gameevent endpoint
All game methods (opengame, placebet, collect, etc.) must be served on the /gameevent path — for example, https://your-math-server.com/gameevent.
The SDK server's postToProvider function automatically appends /gameevent to whatever server URL is configured in the environment variable (e.g. GO3_SERVER_URL). This means:
- Using an existing Reelsoft math server? This just works — Reelsoft's contract requires
/gameeventbecause other methods exist in parallel on the same server. - Building your own RGS or mock? You must serve all game methods at the
/gameeventpath, or the SDK server will not be able to reach them.
Core methods
| Method | Purpose | When to call |
|---|---|---|
opengame | Start a session. Returns config, bet levels, balance, feature flags. | On game load |
placebet | Place a bet and receive the math result. Returns the full "play script" for animations. | When the player bets |
nextaction | Advance a multi-step round. The client sends an actionCode (CONTINUE or CASH_OUT) and receives the updated round state. | After placebet in step-based games (e.g. Stepper) |
collect | Finalize the round and settle winnings with the wallet. | After all animations complete (single-outcome games like Go3) |
Not all games use every method
Go3 / Rippin Rumble: placebet → collect. The round resolves in one step. Stepper: placebet → nextaction (repeated) → round ends on crash or cash-out. No separate collect call — settlement happens inside nextaction.
Supporting methods
| Method | Purpose |
|---|---|
checkfreebet | Check if the player has free bets available (Stepper) |
readhistory | Fetch the player's recent rounds (paginated) |
readreplay | Fetch math data for a previous round (within current session) |
openreplay | Load and replay any completed round (standalone) |
Key concepts
requestCounter— Incremented with every request (exceptopengame). Prevents duplicate processing from network issues. Theopengameresponse returnslastRequestCounterto resume from.nextAction— The server tells the client what to do next (e.g.["COLLECT"],["CONTINUE"],["CONTINUE", "CASH_OUT"]). Always follow this — do not invent actions.- All amounts are raw (in cents) — The math server returns all monetary values in the smallest currency unit (e.g.
10000= $100.00 USD). The SDK passes these through unchanged — it never converts or scales them. To display amounts to the player, useformatAmount()from the framework, which handles the cents-to-display conversion using the currency object fromopengame. chipLevels/betLevelsanddefaultBet— Always use server-provided values, never hardcode. Some math servers usebetLevelsinstead ofchipLevels(e.g. Stepper).featureFlags— Jurisdiction-specific settings likeAUTO_PLAY,BUY_FEATURE,POWER_BET. Respect these in your UI.session— Included in every response. Contains play time, round count, and win/loss — required for display in some jurisdictions.
opengame
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "opengame" | Method name |
sessionId | string | "RRTEST286030..." | From the &session= query parameter |
internalClientCode | string | "RIPPIN_RUMBLE" | Hardcoded game identifier — must match the endpoint |
language | string | "en" | (optional) Two-char ISO code |
placebet
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "placebet" | Method name |
sessionId | string | "RRTEST701258..." | Same session ID from opengame |
requestCounter | number | 1 | Incremented counter |
bets | array | [{ "betType": "BASE", "betAmount": 50 }] | Array of bet objects (typically one) |
bets[].betType | string | "BASE" | Game-specific. Go3/Rippin Rumble: "BASE", "BOOSTED". Stepper: "BEGINNER", "EASY", "MEDIUM", "HARD", "INSANE" |
bets[].betAmount | number | 1000 | Bet amount in cents |
testCase | string | "RARE4" | (mock only) Force a specific test outcome |
nextaction
Used by multi-step games (e.g. Stepper/ChickenX) to advance a round one step. After placebet returns nextAction: ["CONTINUE"], the client calls nextaction repeatedly — each call either advances the ladder (SAFE) or ends the round (CRASH). The player can also cash out at any step after the first.
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "nextaction" | Method name |
sessionId | string | "7626712703577953783" | Same session ID from opengame |
requestCounter | number | 3 | Incremented counter |
roundId | string | "7626712755930766164" | The roundId returned by placebet |
actionCode | string | "CONTINUE" | "CONTINUE" (take next step) or "CASH_OUT" (collect current payout) |
language | string | "en" | (optional) Two-char ISO code |
Round endings via nextaction:
- CRASH — A
CONTINUEaction reveals a crash.roundEnded: true,totalWinAmount: 0, all remaining steps show"CRASH". - CASH_OUT — The player sends
actionCode: "CASH_OUT".roundEnded: true,totalWinAmountequals the current payout. Remaining steps are revealed (showing what would have happened).
First step is mandatory
After placebet, the only available action is ["CONTINUE"] — the player must take the first step. CASH_OUT becomes available after at least one successful step returns nextAction: ["CONTINUE", "CASH_OUT"].
collect
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "collect" | Method name |
sessionId | string | "RRTEST709235..." | Same session ID from opengame |
requestCounter | number | 2 | Incremented counter |
roundId | string | "MOCK485868094" | The roundId returned by placebet |
readhistory
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "readhistory" | Method name |
sessionId | string | "RRTEST286030..." | Same session ID from opengame |
requestCounter | number | 3 | Incremented counter |
pageNumber | number | 0 | Zero-based page index |
readreplay
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "readreplay" | Method name |
sessionId | string | "RRTEST286030..." | Same session ID from opengame |
requestCounter | number | 4 | Incremented counter |
roundId | string | "MOCK789790722" | Round ID from readhistory |
openreplay
| Field | Type | Example | Description |
|---|---|---|---|
method | string | "openreplay" | Method name |
roundId | string | "MOCK789790722" | From the &replay= query parameter |
internalClientCode | string | "RIPPIN_RUMBLE" | Game identifier |
Important
- Go3 / Rippin Rumble: If the server indicates
nextAction=["COLLECT"], you must callcollectafter animations end. If you don't, the round stays open and the player never receives the payout. - Stepper: There is no separate
collectcall. Rounds are settled automatically when they end vianextaction— either by crash or cash-out. The SDK'sstepper.collect()method sends aCASH_OUTaction internally.
Error codes
| Code | Name | HTTP | Action |
|---|---|---|---|
| 101 | BAD_REQUEST | 400 | Close game |
| 201 | ACCESS_DENIED | 401 | Close game |
| 202 | RESTRICTED_LOCATION | 401 | Show location error, close |
| 207 | SESSION_NOT_FOUND | 404 | Close game |
| 208 | SESSION_EXPIRED | 403 | Show "Session expired", close |
| 301 | NOT_SUFFICIENT_FUNDS | 402 | Let player lower bet or quit |
| 302 | PLAYER_BLOCKED | 403 | Close game |
| 401 | OUT_OF_SYNCH | 403 | Soft reset (re-run opengame) |
| 500 | INTERNAL_ERROR | 500 | Soft reset, then quit if persistent |
| 501 | COMMUNICATION_FAILURE | 500 | Soft reset, then quit if persistent |
| 503 | SERVICE_DISABLED | 503 | Soft reset, then quit if persistent |
Building your own RGS mock
You can build a local mock math server for development and testing. Your mock needs to implement the core methods for your game type and return responses that follow the contract above.
For single-outcome games (Go3, Rippin Rumble):
opengame— Return config withchipLevels,currency,defaultBet, andbalance.placebet— Accept a bet, generate a math result, return it inmath.details.collect— Accept aroundId, return an updated balance.
For step-based games (Stepper):
opengame— Return config withbetLevels,currency,defaultBet,balance, andextraData.payouts.placebet— Accept a difficulty-basedbetType, generate the step ladder, return it inmath.details.steps.nextaction— AcceptroundId+actionCode(CONTINUEorCASH_OUT), advance the step, return updated ladder with outcomes.
Your mock must serve all methods on a single POST /gameevent endpoint — the SDK server automatically appends /gameevent to the configured server URL. For example, if your mock runs on http://localhost:3000, the SDK server will send requests to http://localhost:3000/gameevent.
This is useful for:
- Developing without network access
- Testing specific edge cases (empty results, max wins, errors)
- Running automated tests against deterministic outcomes
Coming soon: Generic provider
A generic provider is in development that will let you point the SDK at any local mock server without modifying the SDK itself. You'll be able to define your own math schema and connect it directly — no custom provider code needed.
Adding a new math server
Want a custom math model for your game? The process involves:
- Define the math — Specify the game mechanics, payout tables, RTP targets, and result structure.
- Implement in Java — The math engine is built as a Java service following the RGS contract.
- Deploy — The math server is deployed to the RGS infrastructure.
- Connect with RGS — Session management, wallet integration, and round lifecycle are wired up.
- Implement SDK provider — A new provider is added to the SDK so game clients can call
openGame(),placeBet(),collect(), and any game-specific methods (e.g.step()) against the new math.
TIP
You don't need to do any of this yourself. The Rollerz team handles the entire pipeline. To start the process, reach out to us:
- Discord: Join the Rollerz server
- Email: rollerz-support@roomone.ventures
We'll work with you to define the math model and get it live.