Задание для ИИ-агента: подключить Sport Line API
Назначение документа
Этот файл содержит техническое задание для ИИ-агента, который должен подключить Sport Line API к существующему сайту, приложению или backend-сервису клиента.
Изучи архитектуру проекта, используемый язык, фреймворк, соглашения по коду и существующую систему работы с внешними API. Выполни интеграцию в стиле проекта. Не заменяй архитектуру, интерфейс или существующую бизнес-логику без необходимости.
Это задание требует реализации и проверки результата, а не только описания возможного решения. Если пользователь запросил только консультацию или план, не изменяй файлы без его разрешения.
Обязательно перед началом работы
Перед изменением кода изучи документацию Sport Line API, находящуюся в этой папке.
Обязательно прочитай:
- Руководство по интеграции.
- Быстрый старт.
- Авторизацию и доступ.
- Основные понятия.
- Описания методов, которые потребуются для интеграции.
- Соответствующие модели данных и единый справочник полей.
Не начинай реализацию, основываясь только на этом задании. Используй документацию SportAPI как основной источник информации об URL, параметрах, полях, форматах ответов и правилах обновления данных.
Если документация отсутствует или ссылки недоступны, сообщи об этом пользователю до
начала интеграции и попроси передать всю папку client-documentation.
Цель интеграции
Создай безопасное серверное подключение к Sport Line API, которое позволяет:
- Получать актуальную навигацию спортивной линии.
- Показывать доступные Prematch- и Live-матчи.
- Открывать подробные данные выбранного матча.
- Отображать фактически полученные коэффициенты, статистику и субматчи.
- Регулярно обновлять данные с разрешённой частотой.
- Корректно обрабатывать пустые ответы, ошибки доступа и исчезновение матча.
Основная цепочка интеграции:
menu → events → event
Что нужно получить перед началом
Изучи проект и найди или запроси у пользователя:
- Базовый URL Sport Line API, выданный менеджером SportAPI.
- API-ключ, который должен храниться в защищённой переменной окружения.
- Нужные типы линии: Prematch, Live или оба.
- Язык ответа, подключённый к ключу.
- Виды спорта, которые входят в тариф клиента.
- Страницы, компоненты или внутренние API, где будут использоваться данные.
- Требования к отображению матчей, коэффициентов и статистики.
- Нужны ли киберспортивные данные.
- Подключены ли дополнительные сервисы: Live 3D Tracker, видео, результаты или система ставок.
- Требования проекта к кэшу, журналированию, тестам и обработке ошибок.
Не проси пользователя публиковать рабочий API-ключ в общем чате. Предложи добавить его в систему секретов проекта или локальную переменную окружения.
Если обязательных данных нет, подготовь безопасную интеграцию с заполнителями и сообщи, что ещё нужно получить. Не придумывай базовый URL, ключ, ID спорта, ID турнира или матча.
Для получения доступа пользователь обращается к менеджеру SportAPI: @suport_sportapi.
Конфигурация
Используй принятый в проекте механизм конфигурации. Рекомендуемые имена переменных:
SPORTAPI_BASE_URL=https://YOUR_API_DOMAIN
SPORTAPI_PACKAGE_KEY=YOUR_API_KEY
SPORTAPI_LANGUAGE=ru
При необходимости добавь отдельную настройку типа линии:
SPORTAPI_LINE_TYPE=live
Правила:
- не записывай рабочий ключ непосредственно в исходный код;
- не добавляй ключ в Git;
- не передавай ключ в URL;
- не выводи ключ в логи и сообщения интерфейса;
- не отправляй ключ в браузер или мобильное приложение;
- выполняй запросы к Sport Line API через backend клиента;
- проверяй наличие обязательных настроек при запуске приложения.
Один ключ предназначен для одного проекта и одной согласованной среды. Он привязывается к домену или IP-адресу сервера. Не используй рабочий ключ в другой среде без согласования с SportAPI.
Способ подключения
Sport Line API работает через REST API. WebSocket находится в разработке и не должен использоваться в рабочей интеграции до официального запуска.
Все методы выполняются через HTTP GET.
API-ключ передаётся в заголовке:
Package: YOUR_API_KEY
Рекомендуется также передавать:
Accept: application/json
Пример первого запроса:
curl --request GET \
--url 'https://YOUR_API_DOMAIN/v1/menu/live/ru' \
--header 'Package: YOUR_API_KEY'
Создай общий API-клиент
Не дублируй HTTP-логику в каждом методе. Создай один клиент или функцию запроса, которая:
- Получает относительный путь метода.
- Добавляет базовый URL.
- Передаёт заголовки
PackageиAccept. - Устанавливает разумные таймауты соединения и ответа.
- Разбирает JSON.
- Проверяет HTTP-статус.
- Проверяет
error_codeиerror_message. - Проверяет общую оболочку
status,page,body. - Возвращает типизированный или предсказуемый результат.
- Не раскрывает ключ при ошибке.
Используй штатную HTTP-библиотеку и принятый в проекте подход к внедрению зависимостей, конфигурации и обработке исключений.
Общий формат ответа
Успешный ответ
{
"status": 1,
"page": "/v1/menu",
"body": []
}
body может быть массивом, объектом матча, пустым массивом или объектом с сообщением.
Тип зависит от метода.
Не создавай бизнес-логику для неподтверждённых значений status. После проверки
оболочки всегда анализируй тип и содержимое body.
Ошибка API
{
"error_code": 100,
"error_message": "Invalid Package"
}
Проверяй ошибку в JSON, а не только по HTTP-статусу.
Служебное сообщение метода event
{
"status": 1,
"page": "/v1/event",
"body": {
"message": "Game id finished"
}
}
Проверяй body.message до разбора объекта матча.
Prematch и Live
В URL используются два типа линии:
| Значение | Данные |
|---|---|
line | Prematch — матчи, которые ещё не начались |
live | Live — матчи, которые проходят сейчас |
Правила:
- получай и храни Prematch и Live раздельно;
- не смешивай ответы двух типов в одном кэше;
- не меняй
lineнаliveв запросе со старымgame_id; - после перехода матча в Live создаётся новый
game_id; - API не предоставляет готовую связь Prematch-матча с Live-версией;
- если проект сопоставляет их самостоятельно, не выдавай такое сопоставление за гарантированную связь SportAPI.
Шаг 1. Получи актуальное меню
Основной метод навигации:
GET /v1/menu/{type}/{lang}
Ответ содержит:
вид спорта
└── страна
└── турнир
Используй ID только из актуального ответа того же типа линии:
body[].id—sportId;body[].sub[].id—countryId;body[].sub[].sub[].id—tournamentId.
Не создавай постоянный статический список доступных видов спорта и турниров. API
возвращает только разделы, в которых сейчас есть матчи. После исчезновения последнего
матча турнир или весь вид спорта может пропасть из следующего menu.
Если пользователю нужен киберспорт и метод поддерживает такую выборку, добавь:
?cybersport=true
Обычный спорт и киберспорт обрабатывай как отдельные выборки, если этого требует интерфейс проекта.
Шаг 2. Получи список матчей
GET /v1/events/{sportId}/{tournamentId}/sub/50/{type}/{lang}
Обязательные правила метода events:
- используй только формат
sub; - всегда передавай технический сегмент
countсо значением50; - не используй
countдля пагинации — ограничение количества отменено; - передай ID турнира или
tournamentId=0для всех турниров выбранного спорта; - даже при
tournamentId=0получайsportIdиз актуального меню; - используй тот же
typeиlang, что и в выбранной ветке навигации.
Структура ответа:
body[]
└── объект турнира
└── events_list[]
└── матчи
В events находится краткий набор основных групп и лучших коэффициентов. Не выполняй
event для каждого матча автоматически. Запрашивай подробный матч, когда эти данные
действительно нужны пользователю.
Шаг 3. Получи подробный матч
Возьми game_id из выбранного матча и выполни:
GET /v1/event/{gameId}/group/{type}/{lang}
Обязательные правила метода event:
- используй только формат
group; - передавай тот тип
lineилиlive, из которого полученgame_id; - не ожидай массив матчей: успешный
bodyсодержит один объект; - сначала проверяй
body.message; - используй
eventдля полного списка коэффициентов выбранного матча; - сохраняй порядок групп, колонок и исходов, сформированный API.
Формат group уже группирует и сортирует коэффициенты. Не перестраивай структуру без
явного требования интерфейса.
Идентификаторы
| Назначение | Поле или параметр |
|---|---|
| Вид спорта | sportId в URL, sport_id в объекте матча |
| Страна | countryId в URL, country_id в объекте матча |
| Турнир | tournamentId в URL, tournament_id в объекте матча |
| Матч или субматч | gameId в URL, game_id в JSON |
| Основной матч субматча | game_mid |
| Исход ставки | oc_pointer |
| Live 3D Tracker | zp |
| Видеотрансляция | vi |
Не создавай ID из названий и не подменяй один идентификатор другим.
В частности:
game_idиспользуется для запросаevent;zpпередаётся какgameidготового Live 3D Tracker;viпередаётся в отдельный видеовиджет;oc_pointerиспользуется отдельной системой приёма и расчёта ставок.
Даже если значения отдельных полей иногда совпадают, их назначение остаётся разным.
Матч и Live-данные
Учитывай следующие поля:
game_start— Unix Timestamp в секундах;timer— таймер матча в секундах;score_full— общий счёт;score_period— счёт по периодам;period_name— название текущего периода;finale— признак завершения, который доступен не во всех матчах;extra_time— добавленное время, если поле заполнено.
Для отображения минут раздели timer на 60 и округли согласно требованиям
интерфейса. Не запрашивай API каждую секунду только ради таймера. Обновляй его локально и
синхронизируй при следующем плановом запросе.
Не опирайся на поля game_num, sgame_id, stat_id, stat_list_extra и game_plan:
они устарели, зарезервированы или пока не используются в рабочем API.
Коэффициенты
В списке events
game_oc_list содержит краткий список групп и лучших коэффициентов. Внутри группы
oc_list является плоским массивом:
game_oc_list[]
└── группа
└── oc_list[]
└── исход
В подробном event/group
Внешний массив oc_list содержит колонки, а каждый вложенный массив — исходы выбранной
колонки:
game_oc_list[]
└── группа
└── oc_list[]
└── колонка
└── исходы
Основные поля исхода:
| Поле | Назначение |
|---|---|
oc_name | Название исхода для отображения |
oc_rate | Текущий десятичный коэффициент |
oc_size | Значение тотала, форы или другого параметра |
oc_pointer | Уникальный код ставки или исхода |
oc_block | true — исход заблокирован; false — доступен |
op_id | ID игрока или участника для персональной ставки |
Правила обработки:
- не ожидай обязательную группу
1X2; - не ожидай ничью в теннисе или баскетболе;
- набор рынков зависит от вида спорта и матча;
- используй
group_idкак технический ID группы; - не используй переведённые названия как постоянные ID;
- обновляй исход по
oc_pointer, а не по значениюoc_rate; - если
oc_block: true, не позволяй выбрать исход; - если исход исчез из нового ответа, не показывай старый коэффициент как актуальный;
- не требуй равенства
columnsи количества вложенных массивов; - сохраняй порядок, полученный от API.
Субматчи
Список субматчей возвращается только в подробном event, в поле sub_games.
Это могут быть:
- отдельный тайм, сет или период;
- угловые;
- угловые первого тайма;
- карточки;
- фолы;
- статистика игроков;
- другие дополнительные линии.
Каждый субматч имеет собственный game_id. Запрашивай его тем же методом:
GET /v1/event/{subgameId}/group/{type}/{lang}
Коэффициенты ответа относятся только к выбранному субматчу. Например, коэффициенты субматча «Угловые первого тайма» не относятся ко всем угловым или всему матчу.
Поле game_mid содержит ID основного матча. Не считай sub_games из списка events
источником данных: в events это поле не используется и обычно пустое.
Групповые матчи
Поле event_plan используется только в подробном event для групповых событий.
Основной матч может называться «Хозяева — Гости», а event_plan содержит полный список
конкретных команд, выступающих на каждой стороне. В списке events это поле не
используется.
Не путай event_plan с sub_games.
Live-статистика
Основная статистика находится в stat_list и возвращается только для Live:
- в списке матчей
events; - в подробном матче
event.
Набор показателей зависит от спорта и конкретного матча. Обрабатывай массив динамически
по фактически полученным id, name, opp1 и opp2.
Не переименовывай показатель самостоятельно и не считай статистику субматча отдельной статистикой его типа: в субматче может повторяться статистика основного матча.
Sport Line API не является подробным аналитическим API. История встреч, H2H, анализ команд и игроков относятся к отдельному сервису, который находится в разработке.
Готовые иконки
Для интерфейса можно использовать CDN SportAPI:
| Объект | Шаблон URL |
|---|---|
| Вид спорта | https://cdn.sportapi.net/sports/v1/color/{sportId}.webp |
| Страна | https://cdn.sportapi.net/flags/v1/color/{countryId}.webp |
| Турнир | https://cdn.sportapi.net/tournaments/v1/color/{tournamentId}.webp |
| Команда или участник | https://cdn.sportapi.net/opp/v1/color/{iconName}.webp |
Для команды используй opp_1_icon или opp_2_icon. Перед подстановкой в {iconName}
убери исходное расширение, если оно присутствует.
Предусмотри fallback, если иконка отсутствует или не загружается.
Частота обновления
Интервал означает минимальную паузу между запросами одного набора данных.
| Метод | Live | Prematch (line) |
|---|---|---|
menu | не менее 20 секунд | не менее 60 секунд |
sports, countries, tournaments | не менее 60 секунд | не менее 120 секунд |
events | не менее 7 секунд | не менее 30 секунд |
event | не менее 5 секунд | не менее 30 секунд |
topmatches | не менее 30 секунд | не менее 120 секунд |
toplist | не используется | не менее 120 секунд |
Обязательные правила:
- Не запускай следующий запрос тех же данных, пока предыдущий не завершился.
- Не обновляй
menuс частотойevent. - Не запрашивай
eventдля всех матчей списка без необходимости. - После временной сетевой ошибки используй увеличивающуюся паузу.
- Не повторяй автоматически ошибку ключа, языка, тарифа или параметров URL.
- Если менеджер предоставил другие интервалы, используй значения менеджера.
Жёсткой месячной квоты запросов нет, но нарушение интервалов и чрезмерная нагрузка могут привести к предупреждению и отключению ключа до исправления интеграции.
Кэширование
Кэшировать и обрабатывать ответы на стороне клиента разрешено и рекомендуется.
При реализации кэша:
- учитывай метод и все параметры, изменяющие ответ;
- разделяй
lineиlive; - учитывай язык и признак киберспорта;
- не выдавай старый ответ как актуальный после получения нового пустого массива;
- не сохраняй исчезнувший коэффициент как доступный;
- не помещай API-ключ в ключ кэша или сохранённое тело ответа.
Используй существующую инфраструктуру кэширования проекта. Не добавляй новую базу или внешний сервис, если задача этого не требует.
Пустые состояния и ошибки
Обработай как минимум следующие ситуации:
| Ситуация | Действие |
|---|---|
body: [] | Показать пустое состояние; не считать системной ошибкой |
Game not found | Сообщить, что матч недоступен; обновить список при необходимости |
Game id finished | Прекратить обновление старого ID и запросить актуальные events |
Missing Package header | Проверить передачу заголовка Package |
Invalid Package | Проверить ключ и конфигурацию среды |
Package has expired | Сообщить о необходимости продлить доступ |
Access denied | Проверить тариф и доступный sportId |
Invalid language | Проверить код языка |
The language is not available in your package. | Проверить языки тарифа |
Wrong data type (accept only live or line) | Исправить значение типа линии |
| неизвестный JSON | Зафиксировать безопасную диагностическую ошибку без ключа |
| таймаут или временная ошибка сети | Показать временное состояние и повторить с паузой |
Не определяй по Game id finished, завершился матч, был отменён, перенесён или перешёл
в Live. API не различает эти причины.
Не оставляй бесконечный индикатор загрузки. Используй существующие компоненты проекта для загрузки, пустого состояния и ошибок.
Дополнительные методы
Методы ниже необязательны. Не реализуй и не вызывай их автоматически, если они не нужны проекту:
| Метод | Назначение |
|---|---|
sports | Отдельный список видов спорта |
countries | Страны выбранного спорта |
tournaments | Турниры выбранных спорта и страны |
topmatches | Подборка топ-матчей Live или Prematch |
toplist | Топ-матчи выбранного спорта, только Prematch |
search | Поиск матчей по URL-кодированному тексту |
Обычно используй menu, потому что он возвращает спорт, страну и турнир за один запрос.
Пошаговая цепочка sports → countries → tournaments нужна только для отдельных
сценариев интерфейса.
Не используй метод events-by-period: его контракт требует исправления и пока не готов
для клиентской интеграции.
Live 3D Tracker и видео
Не подключай трекер или видео только потому, что соответствующие поля присутствуют в спортивной линии. Это отдельные платные сервисы со своими ключами и условиями доступа.
Live 3D Tracker
- работает только для Live;
- доступность определяется по
zp; gameidвиджета равенzp, а неgame_id;- при
zp: nullвиджет не создаётся; - вид спорта должен поддерживаться трекером;
- используется готовый
iframeилиembed.js.
Если пользователь явно запросил трекер и имеет доступ, используй отдельное задание для ИИ-агента Live 3D Tracker.
Видеотрансляция
- доступна только для части Live-матчей;
va: 1и непустойviозначают наличие видео;va: nullилиvi: nullозначает отсутствие видео;viявляется строковым ID, а не URL;- видео отображается отдельным готовым виджетом через
iframe; - матчи топовых лиг SportAPI не транслирует.
Не разрабатывай собственный видеоплеер и не подставляй vi напрямую в src без
отдельной документации видеосервиса.
Система приёма ставок
Sport Line API предоставляет данные, но самостоятельно не создаёт купоны, не принимает ставки и не рассчитывает результаты.
Если у клиента подключена отдельная система приёма и расчёта ставок:
- используй
oc_pointerкак уникальный код выбранного исхода; - передавай его без изменения;
- перед выбором проверяй актуальные
oc_rateиoc_block; - следуй документации «Указатель ставки» и «Создание купона».
Не создавай фиктивную отправку ставки только на основании Sport Line API.
Порядок реализации
- Изучи проект и найди существующий HTTP-клиент, конфигурацию, кэш и обработку ошибок.
- Определи backend-слой, в котором безопасно хранится ключ.
- Добавь конфигурацию без секретных значений в репозитории.
- Реализуй общий клиент Sport Line API.
- Добавь модели или типы общей оболочки и используемых методов.
- Реализуй основную цепочку
menu → events → event. - Добавь раздельную работу Prematch и Live, если нужны оба типа.
- Реализуй состояния загрузки, пустого результата и ошибок.
- Добавь кэширование и обновление с нужными интервалами.
- Добавь дополнительные методы только по требованиям пользователя.
- Напиши или обнови тесты.
- Запусти доступные проверки проекта: тесты, линтер, типы и сборку.
- Обнови пример конфигурации и инструкцию запуска без рабочего ключа.
Если проект уже содержит часть интеграции, не создавай параллельную реализацию. Проверь существующий код и расширь его в принятом стиле.
Что запрещено
- Не раскрывай и не логируй API-ключ.
- Не выполняй запросы Sport Line API непосредственно из браузера.
- Не записывай статические ID без проверки актуального
menu. - Не связывай Prematch и Live по
game_id. - Не используй
game_idвместоzpилиvi. - Не считай
status: 1гарантией наличия данных. - Не считай пустой массив системной ошибкой.
- Не ожидай одинаковые рынки, исходы и статистику у всех матчей.
- Не сортируй повторно группы и коэффициенты формата
groupбез необходимости. - Не используй
countкак лимит или пагинацию. - Не запрашивай API каждую секунду ради таймера.
- Не запускай параллельные циклы обновления одних данных.
- Не используй WebSocket до официального запуска.
- Не используй
events-by-periodдо исправления метода. - Не добавляй неподтверждённые поля, статусы или значения.
- Не подключай платные дополнительные сервисы без запроса и доступа клиента.
Проверка результата
После реализации проверь:
- Ключ находится только в защищённой конфигурации backend.
- В запросе присутствует заголовок
Package. - Live- и Prematch-ответы не смешиваются.
- Навигационные ID берутся из актуального API.
eventsвызывается сsub/50.eventвызывается сgroup.tournamentId=0корректно возвращает турниры выбранного спорта.- Плоский
oc_listизeventsи вложенныйoc_listизeventразбираются отдельно. - Группы и исходы не привязаны только к структуре
1X2. - Заблокированный или исчезнувший исход нельзя выбрать как актуальный.
- Субматч запрашивается по собственному
game_id. body: [],Game not foundиGame id finishedобработаны отдельно.- Таймер отображается из секунд и не создаёт секундные API-запросы.
- Интервалы обновления соответствуют документации.
- Повторный запрос не запускается до завершения предыдущего.
- Иконки имеют fallback.
- Необязательные методы не вызываются без необходимости.
- Ключ не попадает в логи, клиентский bundle, тестовые снимки или Git.
- Тесты, линтер, типы и сборка проходят успешно.
- В документации проекта указаны необходимые переменные и способ запуска.
Если нельзя выполнить реальный запрос из-за отсутствия ключа или разрешённой среды, используй сохранённые примеры JSON или тестовые фикстуры. Перечисли внешние проверки, которые пользователь должен выполнить после получения доступа.
Формат отчёта пользователю
После завершения сообщи:
- какие файлы изменены;
- где хранится конфигурация;
- какие методы реализованы;
- как разделены Prematch и Live;
- как обрабатываются коэффициенты, субматчи и статистика;
- какие интервалы обновления используются;
- какие ошибки и пустые состояния реализованы;
- какие тесты и проверки выполнены;
- какие данные, ключи или внешние проверки ещё нужны;
- какие дополнительные сервисы намеренно не подключались.
Подробная документация
Используй следующие документы как основные источники для уточнения структуры и правил работы Sport Line API:
- Клиентское руководство Sport Line API
- Быстрый старт
- Авторизация и доступ
- Основные понятия
menueventsevent- Единый справочник полей
- Коэффициенты
- Статистика
- Субматчи
- Обработка ошибок
- Примеры интеграции
- Частые вопросы SportAPI
Поддержка SportAPI: @suport_sportapi.
Официальный сайт: sportapi.net.