Войти

Вебхуки

Гол, карточка, смена статуса, перенос матча — приходят к вам сами, подписанным 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. Настоящий матч из базы, настоящий автор гола и счёт.

POST https://ваш-адрес/hook
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
Идентификатор события. Он же в заголовке Idempotency-Key: повтор той же доставки узнаётся по нему.
sequence
Номер по порядку внутри матча. Позволяет разложить события в правильном порядке, даже если они пришли не по очереди.
delta
Что именно изменилось.
snapshot
Состояние сразу после изменения — счёт не нужно досчитывать самому.
has_detail
Есть ли по матчу лента событий. Подсказка, стоит ли идти за подробностями.

Названия команд и турнира приезжают в оригинале. Русские названия лежат в карточке матча, которую вы читаете по 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 — тем же способом, с той же подписью. Тишина дольше этого срока означает, что сломан канал, а не футбол.

Ping не мешается

Подписке, которая только что приняла настоящее событие, проверочный запрос не отправляется: она и так жива.

Журнал доставок

В личном кабинете по каждой подписке видно: что ушло, каким кодом ответили, сколько было попыток и когда следующая.

Как подключить

Заведите подписку в кабинете

Адрес приёмника, нужные типы событий и, если надо, фильтры по виду спорта и лигам. Секрет показывается один раз — сохраните его сразу.

Адрес — только https и только публичный

Адреса внутренней сети отклоняются при создании и повторно проверяются перед каждой отправкой. Перенаправления не выполняются.

Проверьте боевым тестом

Кнопка «отправить тестовое событие» шлёт настоящий подписанный запрос на ваш адрес — сразу видно, проходит ли подпись.

Отвечайте быстро

Ответьте 2xx сразу, а разбор сделайте у себя в очереди: на ответ отводится 8 секунд.

До 20 подписок на аккаунт. Вебхуки входят в тарифы Pro и Business — см. тарифы.

Чего нет

Границы канала лучше знать до интеграции, а не во время разбора инцидента.

  • Строгого порядка доставки. Порядок восстанавливается по полю sequence, а не гарантируется транспортом.
  • Ровно одной доставки. Гарантия — «не меньше одной»: после таймаута приедет повтор с тем же ключом. Обработчик обязан быть идемпотентным.
  • Бесконечного хранения. Добор дотягивается на 7 суток назад; за архивом — обычные запросы к матчу.
  • Событий на каждое изменение статистики. Частые изменения детали сведены в один сигнал не чаще раза в 90 секунд на матч — иначе живой тур превратился бы в поток.
  • Обещанного процента доставки. Публичной истории замеров ещё нет, а процент без истории — это обещание, а не факт. Что происходит при отказе, описано выше дословно.

Параметры доставки на этой странице сверены с боевой отдачей 5 августа 2026.

Другие разделы

Получите события матча к себе

Подписка заводится в личном кабинете, тестовое событие уходит на ваш адрес сразу.

Оплата в рублях Договор с ИП / ООО Пробный доступ бесплатно