SportAPI Документация
RU
C Документация продуктаCoupon API
v1
Услуга и цены ↗ Получить доступ ↗
Coupon API / Создание купона

Создание купона

Для регистрации выбранных пользователем ставок используйте:

POST /api/partner/coupons/place

Метод проверяет переданные исходы и создает один или несколько купонов.

В старом API использовался POST /bet/place. Маршрут продолжает поддерживаться, но имеет другой формат ответа и другие коды некоторых ошибок. Для новой интеграции используйте /api/partner/coupons/place. Все необходимые изменения описаны в руководстве «Переход со старого API».

Авторизация

Метод требует клиентский JWT:

Authorization: Bearer <client_token>

Владелец созданных купонов определяется по JWT. Подробнее: «Авторизация».

Минимальный запрос

Для создания купона обязательно передать:

  • list_bets — массив указателей выбранных исходов;
  • amount — положительную сумму ставки.

Пример ординара:

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
  }'

Если mode и multi не переданы, используются безопасные значения по умолчанию:

{
  "mode": "reject",
  "multi": false
}

Полный пример запроса

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
  }'

Поля запроса

ПолеТипОбязательноОписание
list_betsarray[string]ДаОдин или несколько указателей выбранных исходов. Массив не может быть пустым.
amountnumberДаПоложительная сумма ставки.
currencystring/nullНетПроизвольное строковое обозначение валюты, например USD, UAH, COIN или название внутренней валюты партнера.
callback_urlstring/nullНетURL указывает сам партнер. При использовании callback это адрес обработчика результатов; без callback можно передать основной домен сайта партнера.
langstring/nullНетДвухбуквенный код языка названий в данных купона.
modestring/nullНетПравило обработки изменившегося коэффициента: reject или accept. По умолчанию — reject.
mode_typeinteger/nullДля mode = "accept"Дополнительное правило, определяющее, какие изменения коэффициента можно принять. Значения описаны в разделе «Изменение коэффициентов и доступности исхода».
multiboolean/nullНетfalse создает общий купон, true — отдельный ординар для каждого элемента list_bets. По умолчанию — false. Подробности описаны в разделе «Ординары, экспрессы и multi».

list_bets

Каждый элемент массива представляет одну ставку и передается строкой:

{
  "list_bets": [
    "line#737779544#1#1#0#1.85",
    "live#738917381#119#5869#0.5#3.6"
  ]
}

Готовые указатели нужно получать из выбранных исходов спортивной линии или iframe и передавать без изменений. Формат подробно описан на странице «Указатель ставки».

amount

amount — сумма одного создаваемого купона. Она передается как положительное десятичное число без фиксированного количества знаков после запятой:

{
  "amount": 10.5
}

При multi = false это сумма общего ординара или экспресса. При multi = true эта сумма применяется отдельно к каждому созданному ординару. Подробный пример расчета общей суммы приведен в разделе «Ординары, экспрессы и multi».

При успешном создании API автоматически списывает эту сумму с баланса клиентского аккаунта SportAPI. Это отдельный баланс интеграции, а не баланс конечного пользователя в системе партнера.

currency

Передайте обозначение валюты, используемой партнером:

{
  "currency": "USD"
}

Поле не ограничено официальными валютами и не требует кода ISO 4217. Можно использовать обычную, виртуальную, внутреннюю или вымышленную валюту.

Например:

{
  "currency": "COIN"
}

API воспринимает currency как строковое обозначение. Чтобы партнер мог корректно сопоставлять купоны, рекомендуется использовать одно и то же значение для одной валюты во всех запросах создания.

callback_url

Значение callback_url партнер указывает самостоятельно. Если callback используется, передайте полный URL обработчика результатов:

{
  "callback_url": "https://partner.example.com/api/coupon-result"
}
  • в production используйте только https://;
  • в тестовом окружении допускается http://;
  • null, пустая строка или отсутствие поля отключают callback для создаваемого купона;
  • при multi = true URL сохраняется для каждого созданного купона.

Если callback не используется, можно не передавать поле, передать null или пустую строку. Также допускается передать основной домен сайта партнера, например:

{
  "callback_url": "https://partner.example.com"
}

Передавать основной домен вместо endpoint следует только тогда, когда callback для аккаунта не используется. Основной домен не считается URL обработчика callback. Если менеджер включит callback, в новых купонах необходимо указывать полный адрес endpoint, который принимает и обрабатывает запросы POST.

Callback необязателен: актуальные состояния можно получать обычными запросами API. Если партнер хочет использовать callback, об этом необходимо сообщить менеджеру. Менеджер включит доставку и создаст секретную фразу для проверки подписи.

Настройка получателя, подпись и повторы доставки описаны в разделе «Callback».

lang

Передавайте двухбуквенный код языка:

{
  "lang": "en"
}

Этот язык используется для названий спорта, турнира, команд, группы ставок и исхода в данных купона. API поддерживает около 50 языков; полный перечень в документации не публикуется.

Язык фиксируется при создании купона. В дальнейшем купон можно получить только на языке, указанном в lang при его создании. Запросить тот же купон в другом переводе сейчас нельзя — поддержка нескольких языковых вариантов одного купона находится в разработке.

mode и mode_type

Кратко:

  • mode = "reject" — не создавать купон, если коэффициент изменился;
  • mode = "accept" — разрешить прием изменившегося коэффициента по правилу mode_type.

Значения mode_type, ответы при изменении коэффициента и рекомендуемое поведение интерфейса описаны на отдельной странице «Изменение коэффициентов и доступности исхода».

multi

Кратко:

  • multi = false — все элементы list_bets формируют один купон;
  • multi = true — каждый элемент формирует отдельный ординар.

При multi = true будет создано несколько купонов, поэтому успешный ответ всегда содержит массив body.coupons. Финансовое поведение и примеры описаны на странице «Ординары, экспрессы и multi».

Что проверяет API

Перед созданием купона Система расчета купонов SportAPI проверяет:

  1. формат запроса и указателей;
  2. наличие исходов в текущей линии;
  3. блокировку исходов;
  4. актуальность коэффициентов;
  5. отсутствие в одном экспрессе нескольких исходов основного матча и связанных с ним саб-событий;
  6. положительное значение amount;
  7. достаточность баланса клиентского аккаунта для создания всех купонов.

Купон считается принятым только после успешного ответа API.

Важно. Не сохраняйте содержимое корзины партнера как принятый купон до получения подтверждения от API. Корзина содержит только предварительный выбор пользователя. Во время создания Система расчета повторно проверяет исходы: к этому моменту исход может исчезнуть из линии, быть заблокирован или изменить коэффициент. В таком случае API отклонит запрос, и купон не будет принят.

Создавайте в системе партнера запись принятого купона только при code = 1 и сохраняйте купоны, возвращенные в body.coupons. При code = 0 или отсутствии созданных купонов не сохраняйте предварительные данные корзины как принятый купон.

Списание баланса и атомарность

Создание выполняется по принципу «всё или ничего»:

  • при multi = false с баланса клиентского аккаунта списывается один amount;
  • при multi = true списывается amount × количество создаваемых ординаров;
  • все купоны создаются вместе;
  • если общей суммы недостаточно, баланс не изменяется и ни один купон не создается.

Успешный ответ с code = 1 означает, что купоны созданы и соответствующая сумма уже списана с клиентского баланса SportAPI.

Баланс конечного пользователя партнер ведет самостоятельно. Предварительное резервирование и окончательное списание в системе партнера не заменяют автоматическое списание клиентского баланса внутри SportAPI и не выполняются этим API.

Успешный ответ

Пример ответа при создании ординара:

{
  "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"
}

Операция успешна, если одновременно:

  • получен успешный HTTP-ответ;
  • code = 1;
  • body.coupons содержит созданные купоны.

Даже при создании одного купона поле body.coupons является массивом. При multi = true в нём будет отдельный объект для каждого созданного ординара.

Какие данные возвращаются

Каждый элемент body.coupons содержит:

  • данные купона: код, сумму, коэффициенты, возможный и фактический выигрыш, статус и даты;
  • events_data — массив со всеми ставками этого купона;
  • по каждой ставке — исходный указатель, событие, рынок, названия, коэффициенты, статус расчета и другие доступные данные.

Партнер самостоятельно определяет, какие поля купона и ставок необходимо сохранять в своей системе. Однако coupon_code необходимо сохранить обязательно: это связующий ключ для последующего получения и обновления купона.

Храните coupon_code как строку, чтобы не потерять ведущие нули:

000000000272

Идентификатор ставки внутри купона

У купона есть собственный coupon_code, а у каждой ставки внутри events_data — внутренний идентификатор id:

{
  "coupon_code": "000000000272",
  "events_data": [
    {
      "id": 912,
      "game_id": 737779544,
      "status": 0
    }
  ]
}

Если партнер хранит и обновляет ставки по отдельности, рекомендуется сохранять:

coupon_code + events_data[].id

Так можно однозначно найти конкретную ставку внутри конкретного купона.

В callback идентификатор ставки передается строкой в поле events_data[].uuid. Например, uuid = "912" соответствует ставке с id = 912 в полной модели купона.

Поля game_id и bet_id имеют другое назначение: они определяют спортивное событие и тип выбранного исхода, но не являются ID конкретной принятой ставки.

Не путайте идентификатор ставки с batchId: batchId идентифицирует доставку callback, а не купон и не отдельную ставку.

Полное описание возвращаемых полей приведено в разделе «Модель купона и ставки».

Начальное состояние купона

Сразу после создания:

  • купон имеет статус 0;
  • его ставки имеют статус 0;
  • real_win имеет значение null;
  • calculate_coef имеет значение null;
  • calculate_date купона и ставок имеет значение null.

Значение 0 вместо null для calculate_date не используется.

Статусы и последующий расчет описаны в разделе «Статусы и выплаты».

Ошибки создания

error_codeПричина
10Тело запроса не передано.
11Хотя бы один указатель ставки имеет неверный формат.
12amount отсутствует или не является положительным числом.
501Коэффициент изменился и не был принят по заданным правилам.
502Исход отсутствует в текущей линии.
503Исход заблокирован.
504Во время проверки исхода произошла ошибка.
506В один экспресс добавлено несколько исходов одного матча: основное событие и/или связанные саб-события. Подробнее: «Ставки одного матча в экспрессе».
507На балансе клиентского аккаунта недостаточно средств для создания всех купонов.
1002Передан неверный набор параметров.
10000Внутренняя ошибка сервиса.

Ошибки 501504 возвращают сведения о проблемных исходах в body.changes. Не считайте такой ответ успешным только потому, что HTTP-код равен 200.

При недостаточном балансе API возвращает HTTP 200, code = 0:

{
  "code": 0,
  "error_code": 507,
  "error_message": "Insufficient balance",
  "date": 1753000000000,
  "time_ms": 5,
  "path": "/api/partner/coupons/place"
}

При 507 не сохраняйте ни один купон как принятый: операция полностью отклонена, а клиентский баланс не изменен.

При сетевой или серверной ошибке не повторяйте запрос автоматически, пока не исключена возможность, что первый запрос был обработан. Это защищает пользователя от случайного создания дублирующих купонов.

Следующий раздел: «Ординары, экспрессы и multi».