Skip to main content
A free round lets a player spin without paying the stake, while still winning real money. It flows through your wallet like any other round — the stake is simply 0.
Free rounds are not free-to-play. Free-to-play is a demo with virtual money and no callbacks at all. Free rounds are real money: your wallet is called, transactions are created, and winnings are credited.

The model

Campaign

Defines the offer: stake per round, currency, eligible games, validity window. One campaign, many players.

Bonus code

Attaches the campaign to one specific player. One code, one player, one currency.

Setting one up

Pick eligible games

Only games with freeRound: true in List games can be included.

Create the campaign

POST /api/v1/free-rounds/campaigns
amount is the stake redeemed in one round. With maxRounds: 2, a 5 USD campaign is worth 10 USD in total.

Issue bonus codes

POST /api/v1/free-rounds/campaigns/codes, once per player.
userId must be the exact accountId your Player authorization callback returns, and currencyCode must match the campaign currency.

Let the player redeem

The player enters the code in the game. Each spin produces a debit and a credit in your wallet.

Track them

POST /api/v1/free-rounds/campaigns/search lists your campaigns with pagination, and reports isDisabled for any that were switched off.

maxRounds

maxRounds says how many rounds one bonus code grants. Set it on the campaign, on the bonus code, or both. Every round redeems the full campaign amount. 5 USD × 2 rounds = 10 USD in total exposure per code.

In your wallet

Each free spin is a separate bet: its own debit, its own credit, its own transactionId. Both callbacks carry reason: "freeround" and a freeRoundData object:
string
The campaign the round belongs to. Use it to attribute bonus cost in your reporting.
object
The nominal value of one free round, as configured on the campaign. Informational — it is not an amount to move.

What your handlers must do

Debit — stake is 0

Deduct nothing. Still create the transaction and return a valid response with the unchanged balance. Skipping the row breaks the settlement that follows.

Credit — pay exactly what is sent

The stake is already deducted from payout. Credit the amount given, no adjustment.
A losing free round still sends a credit, with payout.amount of 0. Same rule as a paid round — see Wallet integration.

Currency, games and windows

Campaign currency, bonus code currency and the player’s account currency are one value. A player with a EUR account cannot hold a code from a USD campaign — issue a separate campaign per currency.
Every slug in gameSlugs must have freeRound: true. Check the catalogue before creating the campaign rather than debugging the rejection.
startDate and endDate bound when codes can be redeemed. Issuing a code outside its campaign window creates something the player cannot use.
You choose the code string. Make it unique across your platform — collisions between campaigns are your responsibility, not something we can disambiguate.

Searching campaigns

campaignCode and campaignName match on substring, not exact equality. Searching XMAS also returns XMAS-2026-VIP. Filter client side when you need an exact hit.
from and to bound the campaign’s own dates: from returns campaigns whose startDate is on or after it, to returns campaigns whose endDate is on or before it. perPage accepts 1 to 100.