Free cards
Give players free bingo cards through a campaign
Free cards are switched on per partner, on request. Until we switch them
on for your credentials, /freebet/give and /freebet/cancel return HTTP
401 with errorcode: 201. Talk to us to enable them.
A free card grant (a "free bet") gives one player a fixed number of bingo cards at a fixed stake, paid for by your promotion. Every grant belongs to a campaign, which we set up with you before you send any grants.
Free cards work in the multiplayer bingo games we confirm for you at onboarding. They are not available for slots.
How it works
1. You ask us to set up a campaign (game, currency, dates, offer)
2. Your promotion system calls POST /freebet/give for each player
3. The player opens the game (normal /gamelauncher/play launch)
4. The game shows the player their free cards offer
5. The player takes it during a card-buying window
6. We send a FREEBET /debit (player pays 0), then settle the round
with a FREEBET /creditA grant does not need an active player session. You can send it before the player next opens the game.
The diagram below shows the whole flow, lane by lane: your promotion system, our backend, the player, and your wallet. Open it full size.

Campaigns
A campaign is the offer that grants are checked against. Tell us:
| What | Notes |
|---|---|
| Game | The gamecode your players launch with |
| Currency | One currency per campaign |
| Start and end time | Grants are only accepted while the campaign is open |
| Card count | The one card count every grant in this campaign gives |
| Stake per card | The one stake every grant in this campaign gives; must be a stake the game offers |
| Grants per player | How many grants one player can get in this campaign. Default 1 |
Rules to know:
- No open campaign, no grants. A
/freebet/givefor a game and currency with no open campaign is refused. - One open campaign per game and currency at a time. Campaigns for the same game and currency can't overlap.
- You never send a campaign ID. We find the campaign from
operator,gamecode,playercurrencyand the time of your call. - Changing a campaign's offer only affects new grants. Grants already given keep the card count and stake they were given with.
- Ending or deleting a campaign ends its unused grants. The player's offer disappears the next time the game checks.
- Every grant counts toward the per-player limit, including ones that were cancelled or expired unused.
POST /freebet/give
Create a grant for one player at https://api.<domain>/game/freebet/give
(/game/freebet/cancel for cancelling). Same HTTP Basic Auth as
/gamelauncher/play.
{
"operator": "casino_abc",
"playerid": "player_42",
"gamecode": "live-bingo",
"externalfreebetid": "grant_8f2c1a",
"numbets": 10,
"freebetamount": 20,
"playercurrency": "EUR",
"validhours": 48
}Required fields:
| Field | Description |
|---|---|
operator | Your operator identifier with us |
playerid | The player who receives the grant. Must be the playerid you send when that player launches the game |
gamecode | The game the grant is for. Must be the gamecode the player launches with |
externalfreebetid | Your unique ID for this grant. Use a new one for every grant (see below) |
numbets | Number of cards. Must equal the campaign's card count |
freebetamount | Stake per card, in hundredths of playercurrency. 20 means 0.20. Must equal the campaign's stake |
playercurrency | The currency the player plays in. Must match the campaign's currency and the player's launch currency |
validhours | Hours the grant stays usable after it is created |
numbets, freebetamount and validhours must be positive whole numbers. We
convert them to integers first, so any fractional part is dropped.
The endpoint also accepts brand, freebettype and currency. They don't
change validation; currency is kept as a label for audit only. We don't
convert currencies, so freebetamount must already be in playercurrency.
Response
{ "freebetid": "<our-free-bet-id>" }The grant is usable straight away. It expires after validhours, or when the
campaign ends, whichever comes first.
externalfreebetid must be unique per grant
While a grant exists (until it expires), we treat a second call with the same
operator and externalfreebetid as a retry of that grant. It returns the
original freebetid and creates nothing new. If the second call asks for a
different grant (another playerid, gamecode, playercurrency, numbets or
freebetamount), it is refused with externalfreebetid is already used for a different grant. So never reuse one ID for several players (for example, a
campaign or batch ID).
A retry only succeeds while the grant would still pass every check. If the campaign has closed or its offer changed since, the retry is refused like a new grant.
Errors
Missing or wrong credentials, or free cards not switched on for your
credentials, return HTTP 401 with errorcode: 201.
A 5xx means something failed on our side; retry with the same
externalfreebetid. Every other refusal is HTTP 400 with errorcode: 101 and
one of these errormessage values:
errormessage | Meaning |
|---|---|
<field> is required | A required field is missing or empty |
numbets, freebetamount and validhours must be positive | One of them is zero, negative, or not a number |
Game not available | No game found for this operator and gamecode |
Game does not support free cards | The game isn't one of our multiplayer bingo games |
playercurrency does not match instance configuration | The game doesn't run in this currency |
numbets <n> is not a card count this room sells | The game doesn't sell this many cards |
freebetamount <n> is not a stake this room offers in <currency> | The game doesn't offer this stake |
No active free cards campaign for this game in <currency> | No campaign is open right now for this game and currency |
numbets <n> does not match the campaign's <m> cards | Card count differs from the campaign |
freebetamount <n> does not match the campaign's <stake> stake | Stake differs from the campaign. The campaign's stake is shown in main currency units |
Player already got free cards in this campaign | The player has reached the campaign's per-player limit |
externalfreebetid is already used for a different grant | This ID already names a grant for another player or offer |
POST /freebet/cancel
Cancel a grant the player hasn't used yet.
{
"operator": "casino_abc",
"externalfreebetid": "grant_8f2c1a"
}An authenticated, well-formed request always returns HTTP 200:
{ "success": true }true: the grant is now cancelled, or was already cancelled.false: we don't know the grant (including one that expired and was cleaned up), or the player has already used it.
Cancelling does not give the player back their place in the campaign's
per-player limit. With the default limit of 1, you can't cancel a grant and
then give the same player a new one in that campaign.
What the player sees
When the player opens the game with a matching operator, playerid,
gamecode and currency, the game shows their free cards offer. They can put
it off and take it later. If a player holds more than one grant, they see one
at a time, the one expiring soonest first.
The player uses a grant whole, in one round. They can't split it across rounds or change the card count or stake. They take it during a normal card-buying window. In games where each room has a fixed stake, the player uses the grant in the room whose stake matches it.
Wallet calls for a free round
We don't call /getbalance before a free card purchase, because the player
pays nothing.
The card purchase is one /debit for all the cards:
{
"reason": "FREEBET",
"debitamount": 0,
"freebetamount": 200,
"externalfreebetid": "grant_8f2c1a",
"freebetended": false,
"roundstarted": true,
"roundended": false
}Here freebetamount is the total stake for the round in hundredths (10
cards × 0.20 = 2.00 → 200), not the per-card value from /freebet/give.
The round settles with a FREEBET /credit carrying the same grant ID:
{
"reason": "FREEBET",
"creditamount": 250,
"externalfreebetid": "grant_8f2c1a",
"freebetended": true,
"roundended": true
}creditamount is the round's win in the normal wallet amount convention (0
for no win). The other fields are the same as a normal /debit and /credit
(see Direct integration).
With a paid side bet
During a free round the player can still place a paid lucky line side bet. That
is a normal REGULAR /debit with roundstarted: false, and it needs
balance. The round then settles with two credits, in this order:
- The
FREEBETcredit for the cards, withroundended: false. - A
REGULARcredit for the side bet (creditamount: 0if it lost), withroundended: true. This one closes the round.
If the free round fails
If the round fails after the FREEBET debit (for example, the round crashes,
the round is cancelled before it starts, or the debit got a server error), we
send a plain /reverse for that debit. It carries originaltransid but no
reason and no free bet fields. Treat it as handing the grant back to the
player. On our side, the grant becomes usable again once the reverse succeeds.
If the first reverse fails, we keep retrying it in the background (see
retries), but the grant stays used on our
side, so contact support if the player should get it back.
Worked examples
Free round, player wins:
POST /debit { round: R1, trans: T1, reason: FREEBET, debit: 0,
freebetamount: 200, freebetended: false, ended: false }
POST /credit { round: R1, trans: T2, reason: FREEBET, credit: 250,
freebetended: true, ended: true } → round R1 closedFree round with a lucky line bet that lost:
POST /debit { round: R1, trans: T1, reason: FREEBET, debit: 0, ended: false }
POST /debit { round: R1, trans: T2, reason: REGULAR, debit: 25,
roundstarted: false, ended: false } → balance -25
POST /credit { round: R1, trans: T3, reason: FREEBET, credit: 250,
freebetended: true, ended: false } → balance +250
POST /credit { round: R1, trans: T4, reason: REGULAR, credit: 0,
ended: true } → round R1 closedFree round fails, grant handed back:
POST /debit { round: R1, trans: T1, reason: FREEBET, debit: 0, ended: false }
POST /reverse { round: R1, trans: T2, originaltransid: T1, ended: true }
→ grant usable again, round R1 closed