Concepts
Vocabulary and conventions used throughout these docs
A short tour of terms you'll see repeated throughout the integration docs. Skim this once before diving in. Bingo-specific terms are introduced as plain English first.
How the game works (one paragraph)
Players join a room (a shared bingo game with multiple players in it at the same time). They buy one or more cards (each card is a numbered grid). Numbers are called over a live video stream by a human host (the host stream). Players match called numbers on their cards, and at the end of the round (one complete game in that room), winners get paid.
Some rooms also offer slot games inside the same iframe (rolling out; see Slots). Each slot spin is its own small round.
You don't need to understand any of the bingo math to integrate. You only need to know when a round started and ended, and how much money moved.
Players, rounds, and rooms
- Room — a shared live game multiple players join at the same time. Each room runs back-to-back rounds.
- Round — one bingo game from card purchase to result payout. A round
belongs to exactly one room. Each round has a globally unique
roundid. Treat it as an opaque string: most are UUIDs, but some carry a prefix (a slot spin isslots:<uuid>). - Spin — one play of a slot game. Every spin is its own round with its own
roundid, one debit and one credit. - Card — one numbered grid a player has bought for a round. A player can hold several cards in one round.
- Stake / wager — how much a player bets per card (bingo) or per spin (slots). Same thing, two words used interchangeably across the industry.
- Side bet — an optional extra bet a player makes alongside their cards (e.g., "lucky line" — a small extra wager that pays out if the player matches numbers in a specific pattern). Independent from the main card win.
- Settlement — the moment a round's outcome is finalised and money is
paid out to winners. Your wallet endpoint sees this as a
creditcall. - Host stream — the live video of a human host calling balls. Embedded inside our iframe; you don't connect to it separately.
Each player has their own roundid, even when they share a room. Wallet
calls are always per-player, never per-room. Two players in the same bingo
room playing the same round will see two different roundid values in their
wallet logs. Every slot spin gets its own roundid too. This is the most common source of confusion during integration
— keep it in mind when reconciling wallet records.
Session
A session is one player's authorised window to play. Sessions are created
when an aggregator (or you, if integrating directly) calls our
/gamelauncher/play endpoint. Each session carries an operator, brand,
currency, mode, and two IDs:
sessionid— our identifier for the session. We generate it.externalsessionid— your identifier for the session (or your aggregator's). You generate it. While a launch code is still valid (10 minutes), calling/gamelauncher/playagain with the sameoperator,externalsessionidandcurrencyreturns the same session and launch URL rather than creating a duplicate. After that, the same call creates a new session.
A session record lasts 24 hours. The lifetime is fixed at creation — there is no "keep-alive on activity". When it expires, the record is removed passively from our database. We do not currently signal the casino's wallet that a session ended.
When the iframe starts, the game swaps the launch code for a player token that lasts 1 hour. After that, a reload, a reconnect, or a slot spin needs a fresh launch URL.
The launch code embedded in the launch URL is much shorter-lived: 10 minutes. Request a fresh launch URL each time you start a player session.
Launch code
/gamelauncher/play returns a launch URL that contains a short-lived
launchCode. The casino embeds this URL in an iframe. Our frontend exchanges
the launch code for a player token, then loads the game. A launch code can be
exchanged again while it is valid (for example if the iframe reloads during
start-up), and expires after 10 minutes. Treat launch URLs as secret, and
request a fresh one for every new player session.
Transaction
Every wallet operation (debit, credit, reverse) carries a unique
transid (UUID); a retry reuses it. Transaction IDs are idempotency
keys — calling twice with the same transid MUST produce the same result,
not two effects. This
matters because we retry credit and reverse on network failures (3
attempts with exponential backoff, and a reverse that still fails is resent
in the background for a few hours).
Mode
mode is DEMO or REAL. We store it with the session, but today it does
not change how the game behaves: a DEMO session still sends debit and
credit calls to the wallet like a REAL one. For testing, launch against a
test wallet or test player accounts.
Source of truth for round outcomes
This is important: both integration paths reconcile against a wallet record, but which wallet holds that record differs by path.
- Aggregator path: the aggregator's wallet is the source of truth.
When a player wins, we send a
creditcall to the aggregator. Their record of the credit is what your reporting reconciles against. - Direct integration path: the
creditcall we send to your wallet is the source of truth. Your record of that call is the authoritative outcome.
The iframe does not currently emit any lifecycle events to its parent
window — there is no postMessage contract today. Rely on the wallet
records.
Identifiers you'll provide
| Field | Purpose |
|---|---|
operator | Your operator identifier with us — assigned during onboarding |
brand | A sub-identity within your operator. Some operators run multiple brands (different sites, different markets); you can leave it equal to operator if you only have one |
gamecode | Which of our games you're launching (e.g., live-bingo) |
externalsessionid | Your session identifier. See Session for repeat calls |
currency | A currency code configured for your game. Usually ISO 4217 (USD, EUR, GBP, ...), the international currency-code standard. Sweepstakes codes such as SC and GC work when configured |
playerid | Your stable identifier for the player |
country | ISO 3166 two-letter country code for the player. Stored for audit; we don't enforce geo rules from it |
ipaddress | Player's IP address. Stored for audit; we don't enforce geo rules from it |
Money
By default, wallet amounts are sent as integer cents — the main currency unit times 100. There are no decimals or floats in the default wallet contract.
| Currency | Main unit | Wire amount | Example |
|---|---|---|---|
| USD, EUR, GBP | dollar / euro / pound | main × 100 | $1.00 → 100 |
| Any other two-decimal currency | main unit | main × 100 | 0.50 PLN → 50 |
Today only currencies whose minor unit is 1/100 of the main unit are
fully supported. ISO 4217 currencies with a different minor unit (JPY:
none; BHD: 1/1000; cryptocurrencies: variable) need per-operator
handling on our side before go-live — talk to us during onboarding so we can
map your currency to the correct wire convention. Without that mapping,
amounts are still multiplied by 100 even for currencies where that is
incorrect (for example, ¥150 would be sent as 15000).
The wallet adapter owns this conversion. Current direct integrations use this default integer-cents convention. If a future partner needs a different wire amount convention, we add that exception in the wallet adapter rather than in gameplay code.
Currency mismatch
A session is fixed to one currency for its entire lifetime. We do not
convert between currencies. Debit and credit calls carry the session's
currency. Custom integrations that require per-currency wallet lookup may
also receive currency on balance and reverse calls. If the player's wallet
doesn't actually hold that currency, your wallet can refuse the call with
CURRENCY_MISMATCH. Today we treat that like any other refusal: the bet fails
and the player sees a generic error. We don't end the session.
To avoid this, the casino is responsible for either:
- Picking a currency the player's wallet supports before launching, or
- Operating sub-wallets per currency on your side.
Field naming
All HTTP API fields (launcher API and direct-integration wallet endpoints)
are lowercase, no separators — roundid, transid, sessionid,
externalsessionid, playerid, gamecode, debitamount, creditamount,
originaltransid, ipaddress. This matches the existing seamless-wallet
conventions.
Auth
All endpoints (in both directions) use HTTP Basic Auth by default — that's
a Authorization: Basic <base64(username:password)> header on every request.
We issue credentials during onboarding. Rotate on request. For wallet calls to
you, we can use HMAC signing instead (see
Direct integration).
We identify your calls to us by the credentials we issue you. For our calls to your wallet (direct integrators only), we share our egress IP (the public IP our servers use when calling out to the internet) so you can allowlist it.