Seamless wallet protocol
On a seamless brand the player's money stays in your casino. Every time a game needs to read or move that money, Reelgate calls your wallet endpoint. (On a transfer brand you move money in and out with the deposit/withdraw calls of the Operator API instead, and this page does not apply.)
- You give us one HTTPS URL (portal → Brands → Wallet URL).
- We send
POSTwith a JSON body. Theactionfield says what to do:balance,bet,win,rollbackoradjust. - You answer
200with JSON. - Timeouts: 3 s to connect, 6 s to answer. Keep the endpoint fast: the player is waiting on every spin.
Checking our signature
| Header | Value |
|---|---|
X-Reelgate-Key |
the brand API key (tells you which brand) |
X-Reelgate-Timestamp |
unix seconds |
X-Reelgate-Signature |
hex HMAC-SHA256(brand secret, <timestamp>.<raw body>) |
- Reject a call whose signature does not match, or whose timestamp is more than 300 s off your clock.
- Compute the HMAC over the raw body bytes before parsing the JSON.
const expected = crypto.createHmac('sha256', SECRET).update(`${ts}.${rawBody}`).digest('hex');
const ok = sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
Request fields
| Field | In | |
|---|---|---|
action |
all | balance, bet, win, rollback, adjust |
brand |
all | brand code |
player_id |
all | your player id (the one you passed when opening the session) |
currency |
all | session currency, for example EUR |
session_token |
all | the rgt_... token of the session |
game_id, provider |
all | which game |
transaction_id |
money calls | our unique id for this money movement: the idempotency key |
amount |
money calls | decimal string, up to 6 places; never negative except adjust |
round_id |
money calls | the game round; a round can have several bets and wins |
round_closed |
money calls | true on the last leg of the round |
ref_transaction_id |
rollback |
the transaction_id of the bet being refunded |
promo |
win |
true when the win comes from a provider promotion (free spins, tournament prize) |
retry |
re-sent calls | how many times we already tried this call |
request_id |
balance |
unique id of the balance call (for your logs) |
Your answer
Success:
{ "status": "ok", "balance": "98.50" }
The balance is the player's balance in currency after this call. It is shown in the game.
Refusal:
{ "status": "error", "code": "INSUFFICIENT_FUNDS", "message": "Not enough balance", "balance": "0.40" }
- Use
INSUFFICIENT_FUNDSwhen the stake is above the balance. The game shows the player a low-balance message. - Any other
code(for examplePLAYER_BLOCKED,LIMIT_REACHED) refuses the bet, and the code is recorded in the ledger. - An HTTP 5xx, a timeout or a body that is not JSON counts as no answer.
The actions
balance
Return the current balance. Nothing moves.
bet
Take amount from the player.
- If the balance is too low, refuse with
INSUFFICIENT_FUNDSand book nothing. - If you do not answer, we treat the bet as failed and the game does not go on. We then send a
rollbackfor that bet withtransaction_id=<bet id>-cancel. If you did book the bet, give the money back. If you never booked it, answerTRANSACTION_NOT_FOUND(we accept that as done).
win
Add amount to the player. A win can be 0 on a losing round; you may still get a call to close the round.
A win cannot be refused: the game has already paid it. If you do not answer, or you answer with an error, we keep the win and re-send it with the same transaction_id until you book it:
- the waits are 10 s, 20 s, 40 s, and so on, up to 30 min between tries;
- after 30 tries the row turns
failedand shows in the portal ledger.
rollback
Refund the stake named in ref_transaction_id.
- If you never booked that bet, answer
TRANSACTION_NOT_FOUND. - If it was already refunded, answer
okwithout moving money. - An unanswered rollback is re-sent like a win.
adjust
A correction from the game provider. In practice it is a negative amount: the provider took back a win it had paid by mistake.
- Apply it even if the balance goes below zero, or refuse it with an error code. A refused adjust is kept in the ledger for our support team.
Idempotency: the one rule that matters
The same transaction_id must never move money twice.
- Store every
transaction_idyou book. - When the same id comes again, do not book it again: answer
okwith the current balance. You may add"duplicate": true. - We re-send calls after timeouts, so you WILL receive duplicates.
Order of events in a round
bet (rg-101-bet, 1.00) -> balance 99.00
win (rg-102-win, 2.40) -> balance 101.40 round_closed: true
Free-spin rounds can have wins without a bet. Live games can have one bet and the win a minute later.
Testing
- Portal → Brands → Test wallet sends a signed
balancecall to your URL and shows the answer and the latency. - Portal → Sessions → open a test session: you play with test money held on our side, so your wallet is not called and nothing is billed.
- A reference implementation (Node.js, about 140 lines) is available from your account manager: our own mock wallet, which follows this page exactly.