Third-Party integration overview
You can manage the configuration and issuance of free bets through our admin panel. Additionally, we provide a special API that allows for third-party integration with your systems without the need to use our admin panel.
Please refer to the Bonus External section in the documentation .
Authorization
Access to the API is provided via an API token, which should be included in the x-bonus-api-token header. To obtain a token, please contact us .
Example:
curl -X 'POST' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/offer/freebet/create' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api-token' \
-H 'Content-Type: application/json'General methods
Create freebet offer
Endpoint: /api/v1/public/bonus/external/offer/freebet/create
Request: CreateFreebetOfferDto
Response: OfferResponse
Example:
curl -X 'POST' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/offer/freebet/create' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token' \
-H 'Content-Type: application/json' \
-d '{
"name": "Offer Name",
"key": "offer_key",
"publicCustomData": {
"color": 2321,
"publicName": "Test freebet"
},
"description": "description text",
"settings": {
"bonusType": "AllWin",
"feeSponsored": true,
"betRestriction": {
"betType": "All",
"minOdds": "1.5",
"maxOdds": "2.0"
},
"eventRestriction": {
"eventStatus": "All",
"eventFilter": {
"exclude": false,
"filter": [
{
"sportId": "1",
"leagues": [
"Premier League",
"La Liga"
],
"markets": [
{
"marketId": 1,
"gamePeriodId": 1,
"gameTypeId": 1
}
]
}
]
}
},
"periodOfValidityMs": 86400000
}
}'Distribution bonus by offer
Endpoint: /api/v1/public/bonus/external/create
Request: CreateBonusDto
Response: BonusesResponse
Example:
curl -X 'POST' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/create' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token' \
-H 'Content-Type: application/json' \
-d '{
"offerId": "f3f2e850-b5d4-11ef-ac7e-96584d5248b5",
"poolId": "5cf0db52-1a86-46d3-abbf-df262c5be39c",
"recipients": [
{
"address": "f3f2e850-b5d4-11ef-ac7e-96584d5248b5",
"amount": "100"
}
],
"campaignGroup": "campaign-group-1"
}'Get offers list
Endpoint: /api/v1/public/bonus/external/offer/list
Response: OffersResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/offer/list' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Get bonuses
Endpoint: /api/v1/public/bonus/external/list
Parameters:
status(optional):AvailableorUsedsource(optional): which issuance source to list,All,ManualorPromoCode(BonusSource).Allis the default when omittedpage(optional): 1-based page number, at most 10000perPage(optional): number of bonuses per page, from 1 to 200. When omitted, the list is not paginated and returns every bonus
Response: BonusesResponse
Each bonus carries isPromoCode and promoCode: whether it was issued by activating a promo code, and which code. See BonusResponse.
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/list' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Only the bonuses issued by promo codes:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/list?source=PromoCode' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Promo codes
A promo code grants a freebet from an offer and a pool to every bettor who activates it. You create and manage codes with the methods below; bettors activate them on the public endpoint, see the Promo codes guide.
amount is in the base units of the pool’s token: "5000000" is 5 USDT on a 6-decimal token. It is copied as is into every freebet the code issues.
Create promo code
Endpoint: POST /api/v1/public/bonus/external/promo-code/create
Request: CreatePromoCodeDto
Response: PromoCodeResponse
The code is trimmed and upper-cased, must consist of A-Z, 0-9, - and _, 1 to 32 characters, and must be unique.
Example:
curl -X 'POST' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/promo-code/create' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token' \
-H 'Content-Type: application/json' \
-d '{
"code": "SUMMER26",
"offerId": "00000000-0000-4000-8000-000000000001",
"poolId": "00000000-0000-4000-8000-000000000002",
"amount": "5000000",
"maxActivations": 100,
"expiresAt": "2027-06-30T00:00:00.000Z"
}'Get promo codes
Endpoint: GET /api/v1/public/bonus/external/promo-code/list
Parameters:
offerId(optional): only the codes of this offerstatus(optional):ActiveorDeactivated(PromoCodeStatus)
Response: PromoCodesResponse
Returns every code of the product, newest first, with no pagination. Active only means the code is not deactivated: an expired or used-up code is still Active, so compare expiresAt with the current time and activationsCount with maxActivations yourself.
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/promo-code/list?status=Active' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Update promo code
Endpoint: PATCH /api/v1/public/bonus/external/promo-code/update
Request: UpdatePromoCodeDto
Response: PromoCodeResponse
Example:
curl -X 'PATCH' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/promo-code/update' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token' \
-H 'Content-Type: application/json' \
-d '{
"id": "00000000-0000-4000-8000-000000000003",
"expiresAt": "2027-12-31T00:00:00.000Z"
}'Rules:
- Send only the fields you change.
codecan never change. A body that containscodeis rejected with HTTP 400.- After the first activation,
offerId,poolIdandamountare locked. A body that contains any of them is refused, even with the unchanged value, withbonus.update_promo_code_with_activations_error. - After the first activation,
maxActivationsandexpiresAtstay editable, butmaxActivationscannot go belowactivationsCount. Otherwise the request is refused withbonus.promo_code_max_activations_below_used_error.
Deactivate promo code
Endpoint: PATCH /api/v1/public/bonus/external/promo-code/deactivate
Request: DeactivatePromoCodeDto
Response: PromoCodeResponse
Deactivation is final: a deactivated code can never be reactivated. Freebets already issued stay valid.
Example:
curl -X 'PATCH' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/promo-code/deactivate' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token' \
-H 'Content-Type: application/json' \
-d '{
"id": "00000000-0000-4000-8000-000000000003"
}'Errors
Business errors are returned with HTTP 409 and a body { code, message }. Request validation errors are returned with HTTP 400 and a body { message: string[] }.
| Code | When |
|---|---|
bonus.promo_code_code_conflict | A code with that value already exists |
bonus.promo_code_invalid_code | The code does not match the allowed format |
bonus.promo_code_invalid_amount | amount is not positive |
bonus.promo_code_expires_at_in_past | expiresAt is not in the future |
bonus.promo_code_offer_not_freebet | The offer is not a freebet offer |
bonus.promo_code_not_found | No such promo code |
bonus.promo_code_access_denied | The promo code belongs to another product |
bonus.update_promo_code_with_activations_error | offerId, poolId or amount sent for a code that already has activations |
bonus.promo_code_max_activations_below_used_error | maxActivations is below activationsCount |
The offer and pool not-found and access-denied errors are returned the same way.
Statistic methods
These methods display statistics on the bonuses issued
Get bonus statistics by campaign
Endpoint: /api/v1/public/bonus/external/statistics/freebet/by-campaign
Response: BonusStatisticsByCampaignResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/statistics/freebet/by-campaign' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Get bonus statistics by pool
Endpoint: /api/v1/public/bonus/external/statistics/freebet/by-pool
Response: BonusStatisticsByPoolResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/statistics/freebet/by-pool' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Get pools list
Endpoint: /api/v1/public/bonus/external/pool/list
Response: PoolsResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/pool/list' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Utils methods
These methods function as utilities for collecting supplementary information required when constructing an eventFilter
Get unique markets combinations
Endpoint: /api/v1/public/bonus/external/utils/markets-combinations
Parameters:
sportId(required): Sport ID
Response: SportsUniqueMarketsCombinationsResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/utils/markets-combinations?sportId=33' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Get actual sport IDs
Endpoint: /api/v1/public/bonus/external/utils/markets-combinations/sports
Response: ActualSportIdsResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/utils/markets-combinations/sports' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'Get actual leagues
Endpoint: /api/v1/public/bonus/external/utils/leagues
Parameters:
sportIds(optional): Array of sport IDsstartsAtFrom(optional): From time (timestamp)startsAtTo(optional): To time (timestamp)
Response: ActualLeaguesResponse
Example:
curl -X 'GET' \
'https://api.onchainfeed.org/api/v1/public/bonus/external/utils/leagues?sportIds=33&startsAtFrom=1742216019000&startsAtTo=1743339219000' \
-H 'accept: application/json' \
-H 'x-bonus-api-token: api_token'