Выберите язык

Вебхуки

Получайте события активаций на свой сервер в реальном времени, проверяйте заголовок SmsGrab-Signature и разберитесь с повторами, тестовыми доставками и автоматическим отключением.

На этой странице
  1. События
  2. Создание вебхука
  3. Как выглядит доставка
  4. Проверка подписи
  5. Отвечайте быстро
  6. Повторы
  7. Автоматическое отключение
  8. Тест и повторная доставка

Вебхуки отправляют события на ваш сервер в момент, когда они происходят, поэтому опрашивать API не нужно. Вебхук принадлежит одному API-ключу. Он получает события номеров, купленных этим ключом, а также оповещения о низком балансе аккаунта.

События

Событие Когда
activation.created Куплен номер
activation.code_received Каждое новое SMS, со всеми сообщениями на данный момент
activation.completed Завершён вами или по истечении времени после кода
activation.cancelled Отменён до кода, деньги возвращены
activation.expired Код не пришёл вовремя, деньги возвращены
activation.refunded Любой возврат списания
balance.low Баланс опустился ниже заданного вами порога
webhook.test Тестовая доставка, запущенная вами

Создание вебхука

В Аккаунт > Разработчикам откройте ключ и добавьте вебхук с URL, нужными событиями и необязательным описанием. У каждого ключа может быть до 3 вебхуков.

URL должен:

  • начинаться с https://;
  • использовать имя хоста, а не IP-адрес;
  • вести на публичный адрес. Частные сети, localhost и похожие диапазоны отклоняются.

Вы получите секрет для подписи, начинающийся с whsec_. Как и API-ключ, он показывается только один раз. Позже его можно сменить, и это тоже потребует пароль.

Как выглядит доставка

HTTP
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: SmsGrab-Webhooks/1.0
SmsGrab-Event: activation.code_received
SmsGrab-Delivery: 9f7d6c1e-2b44-4c1a-8f0e-6a3d2c1b0e9f
SmsGrab-Signature: t=1790503200,v1=3b9a0c…

{ "id": "evt_4e1f…", "type": "activation.code_received", "created_at": "2026-09-27T10:06:12.004Z",
  "api_version": "2026-09-27", "data": { "activation": { "id": "5c1d0c2e-…", "status": "CODE_RECEIVED" } } }

Проверка подписи

SmsGrab-Signature содержит метку времени t и v1 — HMAC-SHA256 от t, точки и необработанного тела запроса с вашим секретом в качестве ключа. Отклоняйте доставки, у которых метка времени расходится с вашими часами больше чем на 300 секунд, и сравнивайте подписи за постоянное время.

PHP
[$t, $v1] = (function (string $h): array {
    parse_str(str_replace(',', '&', $h), $p);
    return [(int) ($p['t'] ?? 0), (string) ($p['v1'] ?? '')];
})($_SERVER['HTTP_SMSGRAB_SIGNATURE'] ?? '');
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $t.'.'.$body, getenv('SMSGRAB_WEBHOOK_SECRET'));
$ok = abs(time() - $t) <= 300 && hash_equals($expected, $v1);
Python
import hmac, hashlib, time

def verify(header: str, body: bytes, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return abs(time.time() - t) <= 300 and hmac.compare_digest(expected, parts.get("v1", ""))
JavaScript
import crypto from 'node:crypto';

export function verify(header, rawBody, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t ?? 0);
  const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest('hex');
  const given = Buffer.from(parts.v1 ?? '', 'utf8');
  return Math.abs(Date.now() / 1000 - t) <= 300 && given.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(expected, 'utf8'), given);
}

Всегда проверяйте необработанное тело ровно в том виде, в каком вы его получили, до разбора JSON.

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

Ответьте любым статусом 2xx в течение 10 секунд, а долгую обработку выполняйте потом, например в очереди. Перенаправления не выполняются.

Повторы

Неудачная доставка повторяется через 1 минуту, 5 минут, 15 минут, 1 час, 3 часа, 6 часов, 12 часов и 24 часа. Повтор содержит тот же id события, поэтому запоминайте обработанные идентификаторы и пропускайте дубликаты. События одной активации приходят по порядку.

Автоматическое отключение

  • Ответ 410 Gone сразу отключает вебхук.
  • После 50 неудачных попыток подряд на протяжении не менее 24 часов вебхук отключается, и вы получаете уведомление. Исправьте эндпоинт, а затем снова включите вебхук.
  • Отзыв ключа отключает его вебхуки.

Тест и повторная доставка

Отправьте событие webhook.test со страницы вебхука, чтобы сразу увидеть код статуса, время ответа и возможную ошибку. Список доставок хранит каждую доставку 30 дней, и любую из них можно отправить повторно.

Эта статья была полезной?

Всё ещё нужна помощь?

Напишите нам. Мы отвечаем на каждое сообщение, обычно в течение нескольких часов.

Или напишите на support@smsgrab.com