Гол, карточка, смена статуса, перенос матча — приходят к вам сами, подписанным POST-запросом. Не нужно опрашивать API по кругу и гадать, изменилось ли что-нибудь с прошлого раза.
Подписка называет нужные типы — или не называет ни одного, и тогда приходят все, кроме помеченных «по запросу».
| Тип | Когда приходит | Входит по умолчанию |
|---|---|---|
| match.status_changed | Статус матча сменился: запланирован → идёт → перерыв → завершён. | да |
| match.score_changed | Счёт изменился, с указанием стороны. | да |
| match.goal | Гол (в том числе пенальти и автогол) — автор и минута. | да |
| match.card | Карточка, жёлтая или красная — игрок и минута. | да |
| match.lineup_confirmed | Стартовый состав перешёл из предполагаемого в подтверждённый. | да |
| match.rescheduled | Матч перенесён на другую дату или время: в delta приезжают from/to и сдвиг в минутах. | да |
| match.detail_changed | Деталь матча действительно изменилась — статистика, составы, лента. Сигнал «пора перечитать карточку» вместо запроса на каждый гол. Не чаще раза в 90 секунд на матч. | по запросу |
| odds.changed | Обновились коэффициенты матча. Не чаще раза в 60 секунд на матч. | по запросу |
Два типа помечены «по запросу» намеренно: они частые. Подписка «на всё» не должна однажды
начать получать поток, который никто не заказывал, — их нужно назвать явно.
Плюс к списку есть служебный webhook.ping, о нём ниже.
Гол на 59-й минуте матча Краснодар — Факел Воронеж, РПЛ, 2 августа 2026. Настоящий матч из базы, настоящий автор гола и счёт.
Content-Type: application/json User-Agent: SportWire-Webhooks/1.0 X-SportWire-Timestamp: 1785686340 X-SportWire-Signature: sha256=9f2c… X-SportWire-Event-Id: evt_11220580_17 Idempotency-Key: evt_11220580_17 { "id": "evt_11220580_17", "type": "match.goal", "created_at": "2026-08-02T18:12:20Z", "sequence": 17, "data": { "match": { "id": 11220580, "sport": "football", "status": "live", "tournament": {"id": 36196, "name": "Russian Premier League"}, "home": {"name": "FC Krasnodar"}, "away": {"name": "Fakel Voronezh"}, "has_detail": true }, "delta": { "kind": "goal", "side": "home", "minute": 59, "player": "Nikita Krivtsov" }, "snapshot": {"home_score": 3, "away_score": 0} } }
Названия команд и турнира приезжают в оригинале. Русские названия лежат в карточке матча,
которую вы читаете по id из конверта —
см. русские названия.
Подпись — HMAC-SHA256 по строке «время, точка, тело запроса», секрет выдаётся при создании подписки и больше нигде не показывается. Время входит в подписываемое, поэтому перехваченное тело нельзя переслать заново со свежими часами.
Отклоняйте запрос, если X-SportWire-Timestamp отличается от вашего времени больше чем на 5 минут.
Именно по байтам, которые пришли, — до разбора JSON. Пересобранный из объекта текст даст другую подпись.
Сравнением, устойчивым к замеру времени: hmac.compare_digest, hash_equals.
При смене секрета 24 часа приходят обе подписи через запятую. Подходит любая — примите запрос, если совпала хотя бы одна.
# Python import hmac, hashlib, time def verify(secret, ts, raw_body, header): if abs(time.time() - int(ts)) > 300: return False mine = hmac.new(secret.encode(), ts.encode() + b"." + raw_body, hashlib.sha256).hexdigest() for token in header.split(","): got = token.strip().removeprefix("sha256=") if hmac.compare_digest(mine, got): return True return False // PHP $mine = hash_hmac('sha256', $ts . '.' . $raw, $secret); foreach (explode(',', $header) as $t) { if (hash_equals($mine, ltrim(trim($t), 'sha256='))) { /* ok */ } }
Доставка считается удавшейся, только если пришёл ответ 2xx. Всё остальное — таймаут, 500, разрыв — повод повторить.
Через 1 с · 5 с · 30 с · 2 мин · 5 мин. Всего попыток — 6, на каждую даётся 8 секунд.
У каждой доставки свой Idempotency-Key. Повтор после вашего таймаута приедет с тем же ключом — примите его как тот же самый.
События одной подписки, накопившиеся за такт, уезжают ОДНИМ запросом — до 500 штук в теле {"count": N, "events": […]}, с общим заголовком X-SportWire-Batch-Size.
После 5 подряд исчерпанных доставок подписка встаёт на паузу и владельцу уходит письмо.
Через 15 минут после паузы приходит одиночная проба, дальше реже — до 6 часов между попытками. Как только приёмник ответил, доставка включается обратно.
После возвращения до 500 недоставленных событий уезжают заново, по порядку. Руками ничего запускать не нужно.
Если приёмник лежал дольше, чем длятся повторы, — или вы просто хотите сверить свою копию с нашей, — события забираются запросом, а не просьбой в поддержку.
GET /v1/stream/replay?since=2026-08-02T18:00:00Z&limit=200 &sport=football&event_type=match.goal x-api-key: ваш ключ { "events": [ /* конверты, те же самые */ ], "count": 200, "next_cursor": 98213377, "has_more": true }
since принимает и время, и курсор из прошлого ответа. За один запрос — до
500 событий, вглубь — 7 суток.
Конверты те же, что в доставке: обрабатывать их отдельным кодом не нужно.
Главная беда push-канала: он молчит и когда ничего не происходит, и когда он сломан. Отличить одно от другого должен уметь приёмник, а не догадка.
Если по подписке давно не было удачной доставки, раз в 10 минут приходит подписанный webhook.ping — тем же способом, с той же подписью. Тишина дольше этого срока означает, что сломан канал, а не футбол.
Подписке, которая только что приняла настоящее событие, проверочный запрос не отправляется: она и так жива.
В личном кабинете по каждой подписке видно: что ушло, каким кодом ответили, сколько было попыток и когда следующая.
Адрес приёмника, нужные типы событий и, если надо, фильтры по виду спорта и лигам. Секрет показывается один раз — сохраните его сразу.
Адреса внутренней сети отклоняются при создании и повторно проверяются перед каждой отправкой. Перенаправления не выполняются.
Кнопка «отправить тестовое событие» шлёт настоящий подписанный запрос на ваш адрес — сразу видно, проходит ли подпись.
Ответьте 2xx сразу, а разбор сделайте у себя в очереди: на ответ отводится 8 секунд.
До 20 подписок на аккаунт. Вебхуки входят в тарифы Pro и Business — см. тарифы.
Границы канала лучше знать до интеграции, а не во время разбора инцидента.
sequence, а не гарантируется транспортом.Параметры доставки на этой странице сверены с боевой отдачей 5 августа 2026.
Подписка заводится в личном кабинете, тестовое событие уходит на ваш адрес сразу.
Ответим в течение рабочего дня. Пробный доступ бесплатно.
Ответим на
в течение рабочего дня.