Operators
Free bets
Grant a player a number of free rounds on one game. Free rounds never touch your wallet while they are played: KOI keeps the result of every round and, when the bonus ends, pays the total win in a single bonus win callback.
How a bonus works
- You grant the bonus with a
bonus_code, a number of rounds, a stake per round and an expiry date. - The player opens the game and the game offers the bonus. If the player has several bonuses on the same game, the one that expires first is offered first.
- Each free round is played at the granted stake. No bet and no win callbacks are sent for these rounds.
- The bonus ends when the rounds run out, when it expires, or when you cancel it.
- KOI sends one
bonus_winto yourrewardsendpoint with the total win, stake included. The amount can be0.
| How the bonus ends | Rounds played | Callback |
|---|---|---|
| All rounds played | All | bonus_win with the total win. |
| Expired | At least one | bonus_win with the win of the played rounds. |
| Expired | None | None. |
| Cancelled | At least one | bonus_win with the win of the played rounds. |
| Cancelled | None | None. |
A round in progress always finishes before the bonus is closed.
Grant free bets
POST /games/free-bets
Authorization: Bearer <access-token>
Content-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | Your player ID. |
game_slug | string | Yes | Game enabled for your account. |
bonus_code | string | Yes | Your bonus ID, up to 255 characters. Identifies the bonus in the bonus_win callback and is used to cancel it. |
quantity | integer | Yes | Number of free rounds. Positive integer. |
value | number | Yes | Stake of each round. Minimum 0.1. |
expires_at | string | Yes | ISO 8601 expiry date. In the future and at most 30 days from now. |
start_at | string | No | ISO 8601 start date. Must be before expires_at. |
currency | string | No | Currency code. |
operator_free_bet_id | string | No | Your own reference. Repeating it returns the existing grant. |
min_multiplier | number | No | Crash games: minimum cash-out multiplier. Default 1.0. Must be lower than max_multiplier. |
max_multiplier | number | No | Crash, double, wall-street and rush-hour games: maximum multiplier paid per round. Default 10.0. |
extra_data | object | No | Returned unchanged in the response. |
{
"user_id": "player-123",
"game_slug": "aviator-wars",
"bonus_code": "WELCOME-10",
"quantity": 10,
"value": 1.0,
"currency": "BRL",
"expires_at": "2026-12-31T23:59:59Z"
}200 OK
{ "id": 812, "extra_data": null }| Status | When |
|---|---|
401 | Missing or invalid access token. |
404 | The game is not enabled for your account. |
409 | This bonus_code was already granted to this player with a different game, quantity, value or expires_at. |
422 | Validation failed. |
Idempotency
bonus_code is unique per player in your account. Repeating a grant with the same bonus_code, player and parameters returns the existing grant and creates nothing. You can give the same bonus_code to many players: each gets their own bonus.
A new grant never replaces an earlier one. Bonuses on the same game are queued and played one after another.
List a player's free bets
GET /games/free-bets?user_id=player-123
Authorization: Bearer <access-token>Returns the latest 100 bonuses of the player in your account, newest first.
{
"user_id": "player-123",
"free_bets": [
{
"bonus_code": "WELCOME-10",
"game": "aviator-wars",
"status": "active",
"rounds": 10,
"rounds_played": 4,
"rounds_remaining": 6,
"bet_value": 1,
"currency": "BRL",
"start_at": null,
"expires_at": "2026-12-31T23:59:59.000Z",
"created_at": "2026-12-01T10:00:00.000Z"
}
]
}status | Meaning |
|---|---|
active | Can still be played. |
finished | All rounds played and paid. |
expired | Expired before all rounds were played. |
cancelled | Cancelled by you. |
Cancel free bets
POST /games/alea/free-bets/cancel/{bonus_code}
Authorization: Bearer <access-token>
Content-Type: application/jsonWithout a body, cancels the bonus for every player who received this bonus_code in your account. To cancel it for a single player, send:
{ "user_id": "player-123" }Played rounds are kept: if the player had already played, KOI pays their win with a bonus_win. A bonus that was never played is closed without a callback.
200 OK
{ "bonus_code": "WELCOME-10", "cancelled_players": 1 }cancelled_players counts bonuses that were still active. Cancelling again returns 0.
| Status | When |
|---|---|
401 | Missing or invalid access token. |
404 | No bonus with this bonus_code (and user_id, when sent) in your account. |
422 | Validation failed. |
Free bets in callbacks
Free rounds produce no bet, win or rollback callbacks. The only callback is the final bonus win, sent to your rewards endpoint with action: "bonus_win".