HomeBlog › RGS Callback Design

RGS Callback Design: A Checklist for First Integrations

Engineering 27 May 2026 · 9 min read

RGS — Remote Gaming Server — callbacks are how a casino game tells your backend "the player just bet 10 EUR" or "the player just won 75 EUR". Get them wrong and you lose money, every spin, until you fix it.

The five callback events that matter

EventWhat happensYour job
balanceGame asks "how much does this player have?"Return current balance for the session's currency
betPlayer committed to a wagerAtomically deduct from balance; return new balance
winGame pays a winAtomically add to balance; return new balance
refundPrevious bet is being undone (game crash, settlement error)Reverse the bet; return new balance
settle/round-endRound complete; gives you the final stateRecord terminal state for reconciliation

The 12-point pre-launch checklist

  1. HMAC signature verification on every callback. Reject anything that doesn't sign clean with timing-safe compare.
  2. Idempotency keyed on transaction_id from the callback body. First call writes; subsequent calls return cached response.
  3. Atomic balance update. Use a database transaction or a Redis Lua script — never `read → modify → write` in two separate calls.
  4. Currency match between session and callback. If session is BTC, refuse callbacks claiming USD.
  5. Negative balance protection. Reject bet callbacks that would push balance below 0. Return the documented "insufficient funds" code, not 200.
  6. Response time < 3s. Most aggregators time out after 3 seconds and retry. Slow responses get you into double-write territory.
  7. Retry-safe response codes. 5xx tells the aggregator to retry; 4xx tells it to give up. Make sure you only return 5xx when you actually want a retry.
  8. Webhook deduplication at the network layer too — if the aggregator sends the same callback twice from different IPs (e.g., during their failover), your reverse proxy should still hit your idempotency check.
  9. Audit log: every callback (raw body + decision + final balance) into immutable storage. You will need this for disputes.
  10. Session timeout handling. If a callback arrives for a session you've already closed, return the documented "session not found" code, not 500.
  11. Reconciliation cron. Hourly job that compares your tx log against the aggregator's reported activity (API or CSV export). Alert on divergence.
  12. Shadow mode for the first week. Accept all callbacks, return mock responses, log everything. Compare your would-be decisions against the aggregator's actual settlement. Find the bug before it loses money.

The two failure modes that account for 90% of incidents

1. Double-bet

Aggregator sends bet callback. Your server is slow. Aggregator times out at 3s and retries. Now you have two pending writes for the same transaction_id. Without idempotency, you debit the player twice.

Fix: write to your idempotency cache before doing the DB work. If a duplicate arrives, the cache returns the already-computed response.

2. Phantom win

Aggregator sends win callback. You credit the player. Aggregator's session crashes before getting your 200 response. Aggregator retries. You credit again. Player got paid twice.

Fix: same idempotency pattern. Plus: a daily reconciliation job that flags any wins where your record count diverges from the aggregator's.

What to log

Don't sample. The first time a player disputes a balance, you'll want the full trail.

Get a sandbox key Integration docs