Coupon Placement
Use the following endpoint to register the bets selected by a user:
POST /api/partner/coupons/place
The method validates the submitted outcomes and creates one or more coupons.
The old API used
POST /bet/place. This endpoint remains supported, but its response format and some error codes are different. New integrations should use/api/partner/coupons/place. All required changes are described in Migrating from the old API.
Authentication
The method requires a client JWT:
Authorization: Bearer <client_token>
The owner of the created coupons is determined by the JWT. See Authentication for details.
Minimum request
The following fields are required to place a coupon:
list_bets— an array of pointers to the selected outcomes;amount— a positive stake amount.
Example single:
curl --request POST \
--url "$BASE_URL/api/partner/coupons/place" \
--header "Accept: application/json" \
--header "Authorization: Bearer <client_token>" \
--header "Content-Type: application/json" \
--data '{
"list_bets": [
"line#737779544#1#1#0#1.85"
],
"amount": 10
}'
If mode and multi are omitted, the safe defaults are used:
{
"mode": "reject",
"multi": false
}
Complete request example
curl --request POST \
--url "$BASE_URL/api/partner/coupons/place" \
--header "Accept: application/json" \
--header "Authorization: Bearer <client_token>" \
--header "Content-Type: application/json" \
--data '{
"list_bets": [
"line#737779544#1#1#0#1.85"
],
"amount": 10,
"currency": "USD",
"callback_url": "https://partner.example.com/api/coupon-result",
"lang": "en",
"mode": "reject",
"mode_type": null,
"multi": false
}'
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
list_bets | array[string] | Yes | One or more pointers to selected outcomes. The array cannot be empty. |
amount | number | Yes | Positive stake amount. |
currency | string/null | No | Any string identifying the currency, such as USD, UAH, COIN, or the name of the partner’s internal currency. |
callback_url | string/null | No | The partner specifies this URL. When callbacks are used, it is the result handler URL. Without callbacks, the partner’s main website domain may be provided. |
lang | string/null | No | Two-letter language code for names in the coupon data. |
mode | string/null | No | Rule for handling changed odds: reject or accept. Default: reject. |
mode_type | integer/null | For mode = "accept" | Additional rule that determines which odds changes may be accepted. Values are described in Odds changes and outcome availability. |
multi | boolean/null | No | false creates one combined coupon; true creates a separate single for every entry in list_bets. Default: false. See Singles, accumulators, and multi for details. |
list_bets
Each array entry represents one bet and is submitted as a string:
{
"list_bets": [
"line#737779544#1#1#0#1.85",
"live#738917381#119#5869#0.5#3.6"
]
}
Complete pointers must be obtained from selected sports-line outcomes or iframe and submitted without modification. The format is described in detail on the Bet pointer page.
amount
amount is the stake for one coupon being created. It is submitted as a positive decimal number without a fixed number of decimal places:
{
"amount": 10.5
}
With multi = false, this is the stake for the combined single or accumulator. With multi = true, this stake is applied separately to every single created. A detailed total stake example is provided in Singles, accumulators, and multi.
After successful placement, the API automatically debits this amount from the SportAPI client account balance. This is the integration balance, not the end user’s balance in the partner’s system.
currency
Provide the currency identifier used by the partner:
{
"currency": "USD"
}
The field is not limited to official currencies and does not require an ISO 4217 code. It may identify a regular, virtual, internal, or fictional currency.
For example:
{
"currency": "COIN"
}
The API treats currency as a string identifier. To ensure that the partner can associate coupons correctly, use the same identifier for the same currency in every placement request.
callback_url
The partner specifies the callback_url. If callbacks are used, provide the full URL of the result handler:
{
"callback_url": "https://partner.example.com/api/coupon-result"
}
- use only
https://in production; http://is permitted in the test environment;null, an empty string, or an omitted field disables callback delivery for the coupon being placed;- with
multi = true, the URL is stored for every coupon created.
If callbacks are not used, omit the field or provide null or an empty string. The partner’s main website domain may also be provided, for example:
{
"callback_url": "https://partner.example.com"
}
Provide the main domain instead of an endpoint only when callbacks are not enabled for the account. The main domain is not treated as a callback handler URL. If the manager enables callbacks, all new coupons must specify the full endpoint URL that accepts and processes POST requests.
Callbacks are optional: current coupon states can be obtained through regular API requests. A partner that wants to use callbacks must inform the manager. The manager enables delivery and creates a secret phrase for signature verification.
Receiver configuration, signatures, and delivery retries are described in Callbacks.
lang
Provide a two-letter language code:
{
"lang": "en"
}
This language is used for sport, tournament, team, bet group, and outcome names in coupon data. The API supports approximately 50 languages; the full list is not published in this documentation.
The language is fixed when the coupon is placed. The coupon can subsequently be retrieved only in the language specified in lang at placement time. The same coupon cannot currently be requested in another translation. Support for multiple language variants of one coupon is in development.
mode and mode_type
In brief:
mode = "reject"— do not create the coupon if the odds have changed;mode = "accept"— allow changed odds to be accepted according to themode_typerule.
The mode_type values, responses to odds changes, and recommended interface behavior are described separately in Odds changes and outcome availability.
multi
In brief:
multi = false— all entries inlist_betsform one coupon;multi = true— each entry forms a separate single.
With multi = true, several coupons are created, so a successful response always contains the body.coupons array. Financial behavior and examples are described in Singles, accumulators, and multi.
What the API validates
Before creating the coupon, the SportAPI Coupon Settlement System validates:
- the request and pointer formats;
- whether the outcomes exist in the current sports line;
- whether the outcomes are blocked;
- whether the odds are current;
- that an accumulator does not contain multiple outcomes from the main match and its related sub-events;
- that
amountis positive; - that the client account balance is sufficient to create all coupons.
A coupon is considered accepted only after a successful API response.
Important. Do not store the contents of the partner’s bet slip as an accepted coupon before receiving confirmation from the API. The bet slip contains only the user’s preliminary selection. During placement, the Settlement System validates the outcomes again. By that time, an outcome may have disappeared from the sports line, become blocked, or changed its odds. In this case, the API rejects the request and the coupon is not accepted.
Create an accepted coupon record in the partner’s system only when
code = 1, and store the coupons returned inbody.coupons. Whencode = 0is returned or no coupons were created, do not store preliminary bet slip data as an accepted coupon.
Balance debit and atomicity
Coupon placement follows an all-or-nothing rule:
- with
multi = false, oneamountis debited from the client account balance; - with
multi = true,amount × number of singles being createdis debited; - all coupons are created together;
- if the total balance is insufficient, the balance remains unchanged and no coupon is created.
A successful response with code = 1 means that the coupons were created and the corresponding amount has already been debited from the SportAPI client balance.
The partner manages the end user’s balance independently. Preliminary reservation and final debiting in the partner’s system do not replace the automatic debit from the SportAPI client balance and are not performed by this API.
Successful response
Example response for a single:
{
"code": 1,
"body": {
"coupons": [
{
"coupon_code": "000000000272",
"amount": 10,
"win": 18.5,
"potential_win": 18.5,
"real_win": null,
"coef": 1.85,
"original_coef": 1.85,
"calculate_coef": null,
"has_return": false,
"date": 1784970000000,
"status": 0,
"asian": false,
"calculate_date": null,
"coupon_type": 1,
"events_count": 1,
"events_data": [
{
"id": 912,
"game_id": 737779544,
"main_game_id": 737779544,
"is_sub_game": false,
"parent_game_id": null,
"raw_pointer": "line#737779544#1#1#0#1.85",
"line_type": "line",
"is_live": false,
"bet_group_id": 1,
"bet_group_name": "Match result",
"bet_id": 1,
"bet_name": "First team to win",
"sport_id": 1,
"sport_name": "Football",
"tournament_id": 10001,
"tournament": "Test tournament",
"event_date": 1784977200000,
"status": 0,
"opp1": "Team 1",
"opp2": "Team 2",
"team1_id": 101,
"team2_id": 102,
"opp_icon1": 101,
"opp_icon2": 102,
"coef": 1.85,
"calc_coef": null,
"bet_score": "line#737779544#1#1#0#1.85",
"calculate_date": null,
"calculate_score": null,
"rate": "0"
}
]
}
]
},
"error_code": null,
"error_message": null,
"date": 1784970000015,
"time_ms": 45,
"path": "/api/partner/coupons/place"
}
The operation is successful when all of the following are true:
- a successful HTTP response was received;
code = 1;body.couponscontains the created coupons.
Even when one coupon is created, body.coupons is an array. With multi = true, it contains a separate object for every single created.
Returned data
Each entry in body.coupons contains:
- coupon data: code, amount, odds, potential and actual payout, status, and dates;
events_data— an array containing all bets in the coupon;- for each bet: the original pointer, event, market, names, odds, settlement status, and other available data.
The partner decides which coupon and bet fields must be stored in the partner’s system. However, coupon_code must always be stored: it is the linking key used to retrieve and update the coupon later.
Store coupon_code as a string to preserve leading zeros:
000000000272
Bet identifier within a coupon
A coupon has its own coupon_code, while every bet in events_data has an internal id:
{
"coupon_code": "000000000272",
"events_data": [
{
"id": 912,
"game_id": 737779544,
"status": 0
}
]
}
If the partner stores and updates bets separately, we recommend storing:
coupon_code + events_data[].id
This combination uniquely identifies a specific bet within a specific coupon.
In a callback, the bet identifier is provided as a string in events_data[].uuid. For example, uuid = "912" corresponds to the bet with id = 912 in the full coupon model.
The game_id and bet_id fields have different purposes: they identify the sporting event and selected outcome type, but are not IDs of the specific accepted bet.
Do not confuse the bet identifier with batchId: batchId identifies a callback delivery, not a coupon or an individual bet.
All returned fields are described in Coupon and bet model.
Initial coupon state
Immediately after placement:
- the coupon has status
0; - its bets have status
0; real_winisnull;calculate_coefisnull;calculate_dateisnullfor both the coupon and its bets.
The value 0 is not used instead of null for calculate_date.
Statuses and subsequent settlement are described in Statuses and payouts.
Placement errors
error_code | Cause |
|---|---|
10 | The request body was not provided. |
11 | At least one bet pointer has an invalid format. |
12 | amount is missing or is not a positive number. |
501 | The odds changed and were not accepted under the specified rules. |
502 | The outcome is not available in the current sports line. |
503 | The outcome is blocked. |
504 | An error occurred while validating the outcome. |
506 | One accumulator contains multiple outcomes from the same match: the main event and/or related sub-events. See Bets from the same match in an accumulator. |
507 | The client account balance is insufficient to create all coupons. |
1002 | An invalid set of parameters was provided. |
10000 | Internal service error. |
Errors 501–504 return details about affected outcomes in body.changes. Do not treat the response as successful only because the HTTP status is 200.
When the balance is insufficient, the API returns HTTP 200 with code = 0:
{
"code": 0,
"error_code": 507,
"error_message": "Insufficient balance",
"date": 1753000000000,
"time_ms": 5,
"path": "/api/partner/coupons/place"
}
When 507 is returned, do not store any coupon as accepted. The entire operation was rejected and the client balance was not changed.
After a network or server error, do not retry the request automatically until you have ruled out the possibility that the first request was processed. This protects the user from accidental duplicate coupons.
Next section: Singles, accumulators, and multi.