Coupon API — примеры запросов cURL
На этой странице показан проверенный сценарий: авторизация, получение актуального исхода из Sport Line API, формирование полного указателя ставки, создание ординара и получение созданного купона.
Перед началом
Понадобятся curl и jq. Подготовьте переменные только в текущей серверной сессии:
COUPON_API_BASE_URL='https://YOUR_COUPON_API_DOMAIN'
COUPON_LOGIN='YOUR_LOGIN'
COUPON_PASSWORD='YOUR_PASSWORD'
SPORT_LINE_BASE_URL='https://YOUR_SPORT_LINE_DOMAIN'
SPORT_LINE_PACKAGE='YOUR_SPORT_LINE_API_KEY'
Не добавляйте реальные значения в исходный код или документацию.
Шаг 1. Получите JWT
LOGIN_RESPONSE=$(curl --silent --show-error --request POST \
--url "$COUPON_API_BASE_URL/api/partner/login" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data "$(jq -nc \
--arg username "$COUPON_LOGIN" \
--arg password "$COUPON_PASSWORD" \
'{username:$username,password:$password}')")
TOKEN=$(printf '%s' "$LOGIN_RESPONSE" | jq -er \
'select(.code == 1) | .body.token')
Не выводите $TOKEN в журнал. Если jq завершился с ошибкой, изучите безопасную часть
ответа:
printf '%s' "$LOGIN_RESPONSE" | jq \
'{code, error_code, error_message, path}'
Подробнее: «Авторизация».
Шаг 2. Найдите матч в спортивной линии
Сначала получите актуальное Live-меню:
curl --request GET \
--url "$SPORT_LINE_BASE_URL/v1/menu/live/en" \
--header "Package: $SPORT_LINE_PACKAGE" \
--header 'Accept: application/json'
Выберите sport_id и tournament_id, затем запросите матчи:
SPORT_ID='SPORT_ID_FROM_MENU'
TOURNAMENT_ID='TOURNAMENT_ID_FROM_MENU'
curl --request GET \
--url "$SPORT_LINE_BASE_URL/v1/events/$SPORT_ID/$TOURNAMENT_ID/sub/50/live/en" \
--header "Package: $SPORT_LINE_PACKAGE" \
--header 'Accept: application/json'
Возьмите актуальный game_id из body[].events_list[]. Подробности приведены в
описаниях методов menu и
events.
Шаг 3. Получите исход и коэффициент
GAME_ID='GAME_ID_FROM_EVENTS'
EVENT_RESPONSE=$(curl --silent --show-error --request GET \
--url "$SPORT_LINE_BASE_URL/v1/event/$GAME_ID/group/live/en" \
--header "Package: $SPORT_LINE_PACKAGE" \
--header 'Accept: application/json')
Выберите первый незаблокированный исход без персонального player_id:
SELECTION=$(printf '%s' "$EVENT_RESPONSE" | jq -ec '
[.. | objects
| select(
has("oc_pointer") and
(.oc_block == false or .oc_block == 0 or .oc_block == null) and
(.oc_rate | type == "number") and
(.op_id == null)
)
] | first
')
OC_POINTER=$(printf '%s' "$SELECTION" | jq -r '.oc_pointer')
COEFFICIENT=$(printf '%s' "$SELECTION" | jq -r '.oc_rate')
Проверить выбранный исход без вывода доступов:
printf '%s' "$SELECTION" | jq \
'{oc_name, oc_group_name, oc_pointer, oc_rate}'
Подробнее: event и
«Коэффициенты и группы ставок».
Шаг 4. Сформируйте полный указатель ставки
oc_pointer спортивной линии содержит технические части
game_id|group_id|type_id|rate, но не является полным указателем Coupon API. Для Live
добавьте тип линии и актуальный oc_rate:
NORMALIZED_POINTER=${OC_POINTER//|/#}
BET_POINTER="live#$NORMALIZED_POINTER#$COEFFICIENT"
Результат имеет формат:
live#game_id#group_id#type_id#rate#coefficient
Для Prematch используйте запросы линии с типом line и префикс line. Не используйте
устаревший коэффициент: непосредственно перед созданием купона повторно получите исход.
Подробнее: «Указатель ставки».
Шаг 5. Создайте тестовый ординар
PLACE_RESPONSE=$(curl --silent --show-error --request POST \
--url "$COUPON_API_BASE_URL/api/partner/coupons/place" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data "$(jq -nc \
--arg pointer "$BET_POINTER" \
'{
list_bets: [$pointer],
amount: 10,
currency: "USD",
callback_url: null,
lang: "en",
mode: "reject",
mode_type: null,
multi: false
}')")
Покажите только основные поля результата:
printf '%s' "$PLACE_RESPONSE" | jq '{
code,
error_code,
error_message,
coupons: [.body.coupons[]? | {
coupon_code,
amount,
coef,
status
}]
}'
Успех подтверждается одновременно HTTP-ответом без ошибки и code = 1. Сохраните
body.coupons[].coupon_code как строку: код может содержать ведущие нули.
Подробнее: «Создание купона».
Шаг 6. Создайте экспресс
Для экспресса подготовьте минимум два актуальных указателя из разных матчей:
BET_POINTER_1='live#GAME_ID_1#GROUP_ID#TYPE_ID#RATE#COEFFICIENT'
BET_POINTER_2='live#GAME_ID_2#GROUP_ID#TYPE_ID#RATE#COEFFICIENT'
Не объединяйте в экспресс исходы основного матча и его саб-событий. Все элементы
list_bets должны относиться к разным матчам.
Отправьте указатели с multi: false:
EXPRESS_RESPONSE=$(curl --silent --show-error --request POST \
--url "$COUPON_API_BASE_URL/api/partner/coupons/place" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data "$(jq -nc \
--arg pointer1 "$BET_POINTER_1" \
--arg pointer2 "$BET_POINTER_2" \
'{
list_bets: [$pointer1, $pointer2],
amount: 10,
currency: "USD",
callback_url: null,
lang: "en",
mode: "reject",
mode_type: null,
multi: false
}')")
Проверьте структуру созданного экспресса:
printf '%s' "$EXPRESS_RESPONSE" | jq '{
code,
error_code,
error_message,
coupons: [.body.coupons[]? | {
coupon_code,
amount,
coef,
coupon_type,
events_count,
status
}]
}'
Успешный ответ содержит один элемент body.coupons, coupon_type = 2 и
events_count = 2. Поле amount относится ко всему экспрессу, а coef содержит
итоговый коэффициент.
Шаг 7. Создайте несколько ординаров через multi
Чтобы те же два указателя стали отдельными ординарами, передайте multi: true:
MULTI_RESPONSE=$(curl --silent --show-error --request POST \
--url "$COUPON_API_BASE_URL/api/partner/coupons/place" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data "$(jq -nc \
--arg pointer1 "$BET_POINTER_1" \
--arg pointer2 "$BET_POINTER_2" \
'{
list_bets: [$pointer1, $pointer2],
amount: 10,
currency: "USD",
callback_url: null,
lang: "en",
mode: "reject",
mode_type: null,
multi: true
}')")
Проверьте отдельные купоны и общую сумму:
printf '%s' "$MULTI_RESPONSE" | jq '{
code,
coupon_count: (.body.coupons | length),
total_amount: ([.body.coupons[].amount] | add),
coupons: [.body.coupons[] | {
coupon_code,
amount,
coef,
coupon_type,
events_count,
status
}]
}'
При двух указателях API возвращает два ординара с разными coupon_code. Значение
amount применяется полностью к каждому ординару: при amount = 10 общая сумма равна
20, а не 10.
Подробнее: «Ординары, экспрессы и multi».
Шаг 8. Получите созданный купон
COUPON_CODE=$(printf '%s' "$PLACE_RESPONSE" | jq -er \
'select(.code == 1) | .body.coupons[0].coupon_code')
COUPON_RESPONSE=$(curl --silent --show-error --request GET \
--url "$COUPON_API_BASE_URL/api/partner/coupons/get?coupon_code=$COUPON_CODE" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN")
В этом методе один купон находится непосредственно в body, а не в
body.coupons. Выведите его состояние и статусы ставок:
printf '%s' "$COUPON_RESPONSE" | jq '
def coupon_status:
{"0":"NEW", "2":"WIN", "4":"LOSE", "8":"RETURN", "15":"UPDATE"}
[tostring] // "UNKNOWN";
def bet_status:
{"0":"NET", "1":"WIN", "2":"LOSE", "3":"RETURN", "4":"RECALCULATE",
"21":"HALF_WIN", "22":"HALF_LOSE", "23":"PUSH"}
[tostring] // "UNKNOWN";
.body | {
coupon_code,
status,
status_name: (.status | coupon_status),
amount,
coef,
calculate_coef,
real_win,
calculate_date,
events: [.events_data[] | {
game_id,
bet_name,
status,
status_name: (.status | bet_status),
coef,
calc_coef,
calculate_score
}]
}
'
Статусы купона и отдельной ставки имеют разные таблицы значений. Например, 2 означает
выигрыш купона, но проигрыш отдельной ставки. Не интерпретируйте эти поля одной общей
таблицей.
Подробнее: «Получение купона».
Шаг 9. Получите активные купоны
ACTIVE_RESPONSE=$(curl --silent --show-error --request GET \
--url "$COUPON_API_BASE_URL/api/partner/coupons/active" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN")
printf '%s' "$ACTIVE_RESPONSE" | jq '{
code,
count: (.body | length),
coupons: [.body[] | {
coupon_code,
status,
amount,
coef,
coupon_type,
events_count
}]
}'
Массив купонов находится непосредственно в body. Пустой массив является успешным
ответом и означает, что активных купонов сейчас нет.
Шаг 10. Получите недавно рассчитанные купоны
CALCULATED_RESPONSE=$(curl --silent --show-error --request GET \
--url "$COUPON_API_BASE_URL/api/partner/coupons/calculated?time=120" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN")
printf '%s' "$CALCULATED_RESPONSE" | jq '{
code,
count: (.body | length),
coupons: [.body[] | {
coupon_code,
status,
amount,
calculate_coef,
real_win,
calculate_date
}]
}'
Параметр time задаёт окно по времени окончательного расчёта в минутах. Допустимое
значение ограничивается 120 минутами. Активные купоны этот метод не возвращает.
Шаг 11. Получите несколько известных купонов по кодам
COUPON_CODE_1='FIRST_COUPON_CODE'
COUPON_CODE_2='SECOND_COUPON_CODE'
RESULTS_RESPONSE=$(curl --silent --show-error --request POST \
--url "$COUPON_API_BASE_URL/api/partner/coupons/results" \
--header 'Accept: application/json' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data "$(jq -nc \
--arg code1 "$COUPON_CODE_1" \
--arg code2 "$COUPON_CODE_2" \
'{coupon_ids: [$code1, $code2]}')")
printf '%s' "$RESULTS_RESPONSE" | jq '{
code,
count: (.body.coupons | length),
coupons: [.body.coupons[] | {
coupon_code,
status,
amount,
real_win,
coupon_type,
events_count
}]
}'
В групповом методе массив находится в body.coupons. Ответ может содержать меньше
купонов и в другом порядке, поэтому сопоставляйте записи только по coupon_code, а не
по индексу массива.
Подробнее: «Активные и рассчитанные купоны», «Получение купонов списком и по периоду» и «Статусы и расчёт выплаты».
Частые ошибки
| Результат | Причина | Действие |
|---|---|---|
HTTP 401 | JWT отсутствует или больше не действует | Выполнить вход повторно один раз |
error_code = 11 | Передан неполный или неверный указатель | Проверить наличие типа линии и коэффициента |
error_code = 501 | Коэффициент изменился | Повторно получить исход и применить правила mode |
error_code = 502 | Исход исчез из линии | Предложить пользователю выбрать другой исход |
error_code = 503 | Исход заблокирован | Не отправлять ставку повторно без обновления линии |
Не повторяйте запрос создания вслепую после сетевого timeout: первый запрос мог быть принят и повтор создаст второй купон.