Provably Fair
Every classic-game outcome is derived deterministically from three values: a server seed, a client seed, and a nonce. The server seed is committed (hashed) before play and revealed afterward, so a player can recompute any past result and confirm it wasn't altered.
Seed Pairs
Each player holds one seed pair per game, with a lifecycle:
upcoming ──rotate──► active ──rotate──► retired
(hash only) (in use, nonce++) (server seed revealed)
| State | What's visible | Notes |
|---|---|---|
| Active | serverHash, clientSeed, nonce |
The pair in use. nonce increments by one each round. |
| Upcoming | serverHash only |
Pre-committed. Its hash lets the player verify the next seed before they switch to it. |
| Retired | full serverSeed revealed |
A rotated-out pair. The revealed seed is what makes past rounds verifiable. |
Pairs are created automatically on first use, so the client doesn't have to bootstrap them.
Seed Endpoints
All are POST with the session token.
| Endpoint | Purpose | Returns |
|---|---|---|
/seed/current |
The active pair + the upcoming hash. | serverHash, clientSeed, nonce, upcomingServerHash |
/seed/upcoming |
Just the upcoming server hash. | serverHash |
/seed/rotate |
Retire the active pair and promote the upcoming one with a player-chosen client seed. | previousServerSeed, new active { serverHash, clientSeed, nonce }, upcomingServerHash |
/seed/reveal |
Reveal the server seed of a retired pair by id. | serverSeed, serverHash, clientSeed, nonce |
Rotating Seeds
To let a player set their own client seed and reveal the old server seed:
POST /seed/rotate
Authorization: Bearer <token>
{ "clientSeed": "my-chosen-seed" }
{
"previousServerSeed": "a1b2…",
"active": { "serverHash": "c3d4…", "clientSeed": "my-chosen-seed", "nonce": 0 },
"upcomingServerHash": "e5f6…"
}
Rotation is blocked while a round is open (active_round_exists). Finish or cash out the active round first. The new active pair starts at nonce: 0.
Verifying a Result
Once a pair is retired and its server seed revealed, the player can recompute any round it produced via POST /game/verify. The RGS re-runs the same game math with the supplied seeds and returns the raw outcome — no wager, no balance change.
POST /game/verify
Authorization: Bearer <token>
{
"seed": { "serverSeed": "a1b2…", "clientSeed": "my-chosen-seed", "nonce": 42 },
"message": { /* game-specific VerifyRequest */ }
}
{
"message": { "roll": 7421 }
}
The message request and response are game-specific — each game page documents its verify contract. Some verify requests need parameters that shape the result space (e.g. Plinko needs rows + risk; Keno/Wheel/Towers need difficulty), while card games return the resolved deck so the player can replay the deal. Re-running with the same seed triple always yields the same outcome — that's the proof.
How the Outcome Is Derived
The game engine seeds a PRNG with serverSeed, clientSeed, and nonce to produce a deterministic stream of values, which it maps to the game outcome (a roll, a drop path, a shuffled deck). Identical inputs → identical output, every time. Because the server hash is published before the round (commit) and the seed revealed after (reveal), the operator cannot change the seed to alter a result without breaking the hash.