Sport Free Bets (Digitain and Betby)
Sport Free Bets (Digitain and Betby)
Grant, check and cancel free bets on a sportsbook provider. Two sportsbook providers are supported: Digitain and Betby.
All three endpoints are the same for both providers. What changes is the set of fields you send.
| Operation | Endpoint | Method |
|---|---|---|
| Grant a sport free bet | /frb/sport-free-bet |
POST |
| Get sport free bet status | /frb/sport-free-bet/status?operator_id=XXXXX |
POST |
| Cancel a sport free bet | /frb/sport-free-bet/cancel |
POST |
These requests require an authorization token: Bearer authorization token.
Token Format: The authorization token must be Base64-encoded as follows:
AuthorizationToken = encode(back_office_email:back_office_password)
Digitain or Betby: what is different
| Topic | Digitain | Betby |
|---|---|---|
providerName |
Digitain |
Betby, spelled exactly like this |
| Where the rules live | In the request (odds, cash out, bet type, selections, duration) | In a Betby template, created in the Betby back office before granting |
templateId |
Do not send | Required. The ID of the template from the Betby back office |
| Free bet amount | minBet |
minBet, in the player’s currency, up to 2 decimals, at least 0.01 |
duration |
Required, greater than 0 (minutes) | Optional. The validity set in the Betby template applies |
| Odds and rules fields | Required (see below) | Not needed. If sent, they are ignored |
| Players per request | One | One |
Betby templates are created in the Betby back office, not through the Groove API. Create the template there first,
then send its ID as templateId in every grant. The template defines the bonus type, the allowed sports and markets,
the odds limits and the validity period.
Grant a sport free bet
Grant one free bet to one player.
Request endpoint: /frb/sport-free-bet
Request Method: POST
Request parameters:
| Parameter | Data type | Digitain | Betby | Description |
|---|---|---|---|---|
| providerName | String | Required | Required | Digitain or Betby. |
| operatorId | Integer | Required | Required | Groove operator ID. |
| grooveGameId | String | Required | Required | The Groove game ID of the sportsbook for your brand. |
| playerId | String | Required | Required | The player ID. |
| playerCurrency | String | Required | Required | ISO 4217 currency code of the player. |
| playerCountry | String | Required | Required | Country code of the player. |
| playerCity | String | Required | Required | City of the player. |
| offerName | String | Required | Required | A name for the offer. |
| transactionId | String | Required | Required | Unique ID of this request, generated by the casino. A repeated transactionId returns the first result. |
| minBet | Decimal | Required | Required | The free bet amount. For Betby: at most 2 decimals, at least 0.01. |
| templateId | String | — | Required | Betby template ID from the Betby back office. |
| duration | Integer | Required | Optional | Validity in minutes. Digitain: greater than 0. Betby: not sent to Betby, the template validity applies. |
| userBonusTypeId | Integer | Required | — | Digitain bonus type ID. |
| maxCashOut | Decimal | Required | — | Maximum cash out. Greater than 0. |
| minTotalOdd | Decimal | Required | — | Minimum total odd. Greater than 0. |
| maxTotalOdd | Decimal | Required | — | Maximum total odd. Greater than 0 and not lower than minTotalOdd. |
| minWageringOdd | Decimal | Optional | — | Minimum wagering odd. Not higher than maxWageringOdd. |
| maxWageringOdd | Decimal | Optional | — | Maximum wagering odd. |
| allowedBetTypeId | Integer | Optional | — | Allowed bet type. |
| minNumberOfSelections | Integer | Optional | — | Minimum number of selections in the bet. |
| oneTimeBet | Boolean | Optional | — | The free bet can be used in one bet only. |
| bonusEventTypeId | Integer | Optional | — | Bonus event type. |
| sportIds | String | Optional | — | Allowed sports. |
| tournamentIds | String | Optional | — | Allowed tournaments. |
| gameIds | String | Optional | — | Allowed events. |
| Authorization | Header | Required | Required | Sinatra back office user. |
“—” means the field is not used for this provider. If you send it, it is ignored.
Request body: Betby
{
"providerName": "Betby",
"operatorId": 11,
"grooveGameId": "XXXXXXXXX",
"playerId": "player_001",
"playerCurrency": "EUR",
"playerCountry": "MT",
"playerCity": "Valletta",
"offerName": "Weekend free bet",
"transactionId": "550e8400-e29b-41d4-a716-446655440000",
"templateId": "2291845327163297792",
"minBet": 5.00
}Request body: Digitain
{
"providerName": "Digitain",
"operatorId": 11,
"grooveGameId": "236000000",
"playerId": "player_001",
"playerCurrency": "EUR",
"playerCountry": "MT",
"playerCity": "Valletta",
"offerName": "Weekend free bet",
"transactionId": "550e8400-e29b-41d4-a716-446655440001",
"userBonusTypeId": 2,
"duration": 10080,
"minBet": 5.00,
"maxCashOut": 100,
"minTotalOdd": 1.5,
"maxTotalOdd": 10,
"minWageringOdd": 1.5,
"maxWageringOdd": 10,
"allowedBetTypeId": 1,
"minNumberOfSelections": 1,
"oneTimeBet": true,
"bonusEventTypeId": 1
}Success response
The response has the same shape for both providers.
{
"status": "Success",
"data": {
"status": "Success",
"transactionId": "550e8400-e29b-41d4-a716-446655440000",
"bonusId": "2291846012345678901"
}
}Keep bonusId. You need it to check the status and to cancel the free bet.
When the provider rejects the grant, the HTTP code is still 200. data.status is Failed and
data.exceptionResponses holds the reason:
{
"status": "Success",
"data": {
"status": "Failed",
"transactionId": "550e8400-e29b-41d4-a716-446655440000",
"exceptionResponses": ["betby external api config is not available for this casino"]
}
}Get sport free bet status
Get the free bets granted to a player.
Request endpoint: /frb/sport-free-bet/status?operator_id=XXXXX
Request Method: POST
Request parameters:
| Parameter | Data type | Description |
|---|---|---|
| operator_id | Integer required | Groove operator ID (query string). |
| providerName | String required | Digitain or Betby. Must be the provider used for the grant. |
| playerId | String required | The player ID. |
| freeBetIds | Array optional | The bonusId values from the grant response. Empty returns the player’s free bets. |
| currency | String optional | ISO 4217 currency code of the player. |
| Authorization | Header | Sinatra back office user. |
Request body:
{
"providerName": "Betby",
"playerId": "player_001",
"freeBetIds": ["2291846012345678901"],
"currency": "EUR"
}Success response
{
"status": "Success",
"data": {
"items": [
{
"free_bet_id": "2291846012345678901",
"player_id": "player_001",
"casino_id": 11,
"currency": "EUR",
"number_of_spins": 1,
"spins_used": 0,
"bet_amount": "5",
"status": "active",
"expiration_date": "2026-10-30T00:00:00Z",
"created_at": "2026-09-30T10:00:00Z"
}
]
}
}Status Index:
| Status | Description | Betby status |
|---|---|---|
| active | The free bet is available. The player can use it. | new, active |
| completed | The player used the free bet. | activated, done |
| expired | The free bet was not used before the expiration date. | expired |
| canceled | The operator canceled the free bet. | revoked |
For Betby, the status of an active free bet is read from Betby on every request. If Betby does not answer, the last known status is returned.
Cancel a sport free bet
Cancel a free bet the player has not used yet. The request is the same for both providers. You do not need to send
providerName: Groove finds the provider from the original grant.
Request endpoint: /frb/sport-free-bet/cancel
Request Method: POST
Request parameters:
| Parameter | Data type | Description |
|---|---|---|
| operatorId | Integer required | Groove operator ID. |
| grooveGameId | String required | The Groove game ID of the sportsbook for your brand. |
| items | Array required | The free bets to cancel. |
| items[].bonus_id | String required | The bonusId from the grant response. |
| items[].player_id | String required | The player ID. |
| items[].request_id | Integer optional | Your ID for this cancel item. |
| Authorization | Header | Sinatra back office user. |
Request body:
{
"operatorId": 11,
"grooveGameId": "XXXXXXXXX",
"items": [
{
"bonus_id": "2291846012345678901",
"player_id": "player_001",
"request_id": 1001
}
]
}Success response
{
"status": "Success",
"data": {
"response_code": 0,
"description": "",
"bonus_id": "2291846012345678901",
"player_id": "player_001",
"request_id": 1001,
"retryable": false
}
}Only an unused free bet can be canceled. response_code other than 0 means the free bet was not canceled.
Betby cancel response codes
For Betby, response_code in the cancel response is one of these. retryable: true means you can send the same
request again later.
| Code | Meaning | Retryable |
|---|---|---|
| 0 | Canceled | No |
| 1005 | Cannot be canceled: the free bet is not found, already used, or ended | No |
| 1007 | Betby is not configured for this operator | No |
| 1100 | Betby returned an error. See description |
No |
| 1101 | Betby is not available | Yes |
| 1102 | Internal error | Yes |
How a Betby free bet reaches the wallet
When the player places a Betby bet with a bonus, Groove sends the normal Transaction API calls to
the casino. Only bonus-money bets carry the bonus ID in frbid; the others are sent as normal real money bets.
| Betby bonus type (back office name) | bonus_type |
Wager amount sent to the casino | frbid sent |
|---|---|---|---|
| Free bet (“bet refund”) | freebet_refund |
0 |
Yes |
| Free money (“free money”) | freebet_freemoney |
0 |
Yes |
| No risk bet (“no risk bet”) | freebet_no_risk |
The real stake | No |
| Combo boost | comboboost |
The real stake | No |
| Global combo boost | global_comboboost |
The real stake | No |
Example from the Betby payout rules: a bet of 5 at odds 3.5.
| Betby bonus type | Wager sent | If the bet wins | If the bet loses |
|---|---|---|---|
| Free bet | 0 |
12.50 (5 × 3.5 − 5) |
0 |
| Free money | 0 |
17.50 (5 × 3.5) |
0 |
| No risk bet | 5 |
17.50 (5 × 3.5) |
5 (the stake returns) |
For combo boost the win amount already includes the boost.
Wins, losses and rollbacks follow the same rule as their bet: frbid is sent only for freebet_refund and
freebet_freemoney. Betby calculates every win amount, including the stake for free money and the boost for combo
boost; Groove passes it to the casino as is.
A combo boost bet keeps the normal round ID. To see that a round used a combo boost, open the round details: the bet and the win show “Combo boost” or “Global combo boost” with the multiplier.
Response codes
| Code | Status | Message |
|---|---|---|
| 200 | success | The request was processed. Check data for the result. |
| 400 | bad request | The request body is not valid JSON. |
| 403 | forbidden access | The user has no access to this operator. |
| 422 | unprocessable entity | A required field is missing or not valid. The response lists each problem. |
| 500 | internal server error | internal server error |
Validation error example (Betby grant without templateId):
{
"status": "Error",
"data": ["template ID is required for provider betby"],
"message": "sport free bet validation failed[template ID is required for provider betby]",
"userFriendlyMessage": "sport free bet validation failed"
}