Документация / Исходящие вебхуки

Исходящие вебхуки

Исходящий вебхук — это сообщение, которое панель отправляет на ваш адрес, когда с аккаунтом хостинга что-то происходит, чтобы другая система могла отреагировать: ваш собственный биллинг, канал в чате, таблица, скрипт провижининга.

Вебхуки доступны администраторам и реселлерам. Администратор узнаёт обо всех аккаунтах. Реселлер узнаёт только об аккаунтах, которые принадлежат ему. Клиенты и API-токены создавать их не могут: вебхуки настраиваются в самой панели, в собственном сеансе человека, чтобы утёкший токен никогда не превратился в постоянный канал событий панели.

Как добавить

Откройте страницу безопасности своего аккаунта (администратор: Безопасность; реселлер: Безопасность входа) и найдите Вебхуки под API-токенами.

  1. Введите адрес, например https://example.com/hooks/panel.
  2. Отметьте нужные события.
  3. Нажмите Добавить вебхук.

Панель один раз показывает секрет подписи (он начинается с whsec_). Скопируйте его сразу. Он хранится в зашифрованном виде и повторно показан быть не может; если вы его потеряли, удалите вебхук и добавьте новый.

У каждого человека может быть не более 10 вебхуков.

Адрес

  • Он должен начинаться с https://. Простой http:// отклоняется, потому что вызов содержит данные аккаунта.
  • Он не должен содержать имя пользователя или пароль. Вместо этого проверяйте подпись.
  • Он может содержать не более 500 символов.
  • Он должен находиться в публичном интернете. Адреса на этом сервере, в частной сети, на интерфейсе loopback или в диапазоне метаданных облачного провайдера отклоняются — и при сохранении адреса, и снова в момент, когда панель подключается (так что имя хоста, которое позже начнёт указывать на частный адрес, тоже не сработает).
  • Перенаправления не выполняются. Указывайте конечный адрес.

События

Событие Когда отправляется
account.created Аккаунт хостинга создан
account.suspended Аккаунт приостановлен
account.unsuspended Приостановленный аккаунт возобновлён
account.deleted Аккаунт удалён
account.activity Другая активность в аккаунте

Кнопка Проверить у каждого вебхука отправляет событие ping, чтобы вы убедились, что ваш адрес отвечает. Одновременно может ожидать только одна проверка.

Что отправляется

Каждый вызов — это HTTP-запрос POST с телом JSON:

{
  "event": "account.created",
  "at": "2026-10-23T08:15:00Z",
  "account": { "id": 42, "username": "example", "domain": "example.com" },
  "detail": "short text about what happened"
}

at — время UTC. У события ping вид {"event":"ping","at":"…","webhook_id":7}.

С каждым вызовом приходят следующие заголовки:

Заголовок Значение
X-Nimbopanel-Event Название события, например account.created
X-Nimbopanel-Delivery Число, идентифицирующее эту доставку. Повтор той же доставки сохраняет то же число, поэтому используйте его, чтобы игнорировать дубликаты
X-Nimbopanel-Timestamp Когда вызов был подписан, в секундах Unix
X-Nimbopanel-Signature sha256= и далее подпись (см. ниже)
Content-Type application/json
User-Agent Nimbopanel-Webhook/1

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

Запрос на ваш адрес может отправить кто угодно. Подпись — это способ узнать, что вызов пришёл из вашей панели.

Подпись — это HMAC-SHA256 в шестнадцатеричном виде от метки времени, точки и необработанного тела ровно в том виде, как оно получено, вычисленный с вашим секретом подписи:

X-Nimbopanel-Signature == "sha256=" + hex( HMAC_SHA256( secret, X-Nimbopanel-Timestamp + "." + body ) )

Проверяйте в таком порядке:

  1. Вычислите указанное выше значение от необработанного тела запроса (до любого разбора или переформатирования JSON).
  2. Сравните его с заголовком сравнением за постоянное время.
  3. Отклоняйте вызов, если метка времени отличается от ваших часов более чем на 5 минут. Это не даёт повторно воспроизвести старый вызов.
  4. Используйте X-Nimbopanel-Delivery, чтобы игнорировать уже обработанную доставку.

Пример на PHP:

$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_NIMBOPANEL_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_NIMBOPANEL_SIGNATURE'] ?? '';
$want = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($want, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(401);
    exit;
}

Пример на Node.js:

const crypto = require('crypto');
function valid(rawBody, headers, secret) {
  const ts = headers['x-nimbopanel-timestamp'] || '';
  const want = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
  const got = headers['x-nimbopanel-signature'] || '';
  return got.length === want.length
    && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want))
    && Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
}

Ответ, повторы и приостановка

  • Отвечайте любым статусом 2xx в течение 10 секунд. Всё остальное считается неудачей.
  • Неудачный вызов повторяется через 1 минуту, затем через 5 минут, 30 минут и 2 часа. Всего это пять попыток в течение примерно двух с половиной часов, после чего доставка помечается как неудачная.
  • Вызовы на один адрес отправляются по одному, начиная с самых старых. Доставка, ожидающая повтора, не задерживает более новые, поэтому не рассчитывайте, что события придут в строгом порядке. Медленный адрес задерживает только сам себя.
  • После 50 неудачных доставок подряд вебхук приостанавливается: новые события для него больше не ставятся в очередь. Успешное нажатие Проверить сбрасывает счётчик, и события снова идут.
  • Для одного вебхука ожидает не более 200 недоставленных вызовов. Сверх этого новые события для него не ставятся в очередь, пока часть не будет доставлена или не завершится неудачей.
  • Панель хранит для каждого вебхука 50 последних завершённых доставок вместе с полученным ответом, чтобы вы видели, что не удалось. Самые свежие перечислены под вебхуком.

Если вместо статуса панель показывает причину, это одно из: адрес не находится в публичном интернете, нет ответа в течение 10 секунд, имя хоста не существует, сертификат HTTPS недействителен или панель не смогла подключиться.

Хорошие привычки

  • Отвечайте быстро кодом 200 и выполняйте настоящую работу потом. Получатель, который отвечает дольше 10 секунд, выглядит как неудача и получает то же событие снова.
  • Обрабатывайте одну и ту же доставку дважды без вреда. Повторы и сетевые ошибки делают дубликаты возможными.
  • Не храните секрет в репозитории с кодом. Если он утёк, удалите вебхук и добавьте новый.

См. также: Руководство реселлера · Устранение неполадок