LTESocks отправляет события на настроенный endpoint вебхука HTTP-запросом POST с JSON-телом. Вебхуки позволяют реагировать на изменения порта и подключения без постоянного опроса API.
Создание вебхука
Заголовок раздела «Создание вебхука»Создайте новый вебхук в пользовательском кабинете LTESocks. Укажите конечный публичный HTTPS endpoint для приема событий, затем сохраните signing secret в серверном хранилище секретов. Не передавайте секрет в браузерный код, логи или клиентские приложения.
Если кабинет позволяет, отправьте тестовое событие; иначе проверьте следующую реальную доставку до использования интеграции. Для отслеживания завершения смены IP подпишитесь на port.ip_changed и следуйте разделу Сброс и готовность порта.
HTTP-запрос
Заголовок раздела «HTTP-запрос»Каждая доставка имеет следующий вид:
POST /your-webhook-path HTTP/1.1Content-Type: application/jsonX-Signature: BASE64_HMAC_SHA256Подпись рассчитывается по точному телу запроса. Bearer-токен с вебхуком не передается.
Формат события
Заголовок раздела «Формат события»Все события используют версионированную оболочку:
{ "id": "66c5f99e2f66247a9284620f", "version": "v1", "type": "port.ip_changed", "occurred_at": "2026-08-26T09:15:37.123Z", "data": { "port": { "id": "66bca5147010246361dbe256", "service_id": "service-123", "number": 1042, "status": "active" }, "modem": { "id": "66bca4d67010246361dbe213", "name": "modem-kyiv-01" }, "old_ip": "198.51.100.10", "new_ip": "203.0.113.24" }}| Поле | Тип | Значение |
|---|---|---|
id | string | Уникальный идентификатор события. Используйте его как ключ идемпотентности. |
version | string | Версия контракта. Текущее значение — v1. |
type | string | Тип события. |
occurred_at | string | Время события в UTC в формате RFC 3339. |
data.port | object | Порт, связанный с событием. Присутствует всегда. |
data.modem | object | Данные модема для событий, связанных с модемом. |
data.old_ip | string | Предыдущий IP-адрес для port.ip_changed. |
data.new_ip | string | Новый IP-адрес для port.ip_changed. |
Объект port содержит id, service_id, number и status. Объект modem содержит id и name; событие отключения модема также содержит last_seen_at.
Клиент должен игнорировать неизвестные поля, чтобы совместимые расширения формата не ломали обработку.
Типы событий
Заголовок раздела «Типы событий»port.expired
Заголовок раздела «port.expired»Отправляется, когда срок действия порта истек:
{ "id": "66c5f99e2f66247a92846210", "version": "v1", "type": "port.expired", "occurred_at": "2026-08-26T09:20:00Z", "data": { "port": { "id": "66bca5147010246361dbe256", "service_id": "service-123", "number": 1042, "status": "disabled" } }}port.ip_changed
Заголовок раздела «port.ip_changed»Отправляется при смене публичного IP-адреса модема, обслуживающего порт. В событии присутствуют modem, old_ip и new_ip:
{ "id": "66c5f99e2f66247a92846211", "version": "v1", "type": "port.ip_changed", "occurred_at": "2026-08-26T09:21:00Z", "data": { "port": { "id": "66bca5147010246361dbe256", "service_id": "service-123", "number": 1042, "status": "active" }, "modem": { "id": "66bca4d67010246361dbe213", "name": "modem-kyiv-01" }, "old_ip": "198.51.100.10", "new_ip": "203.0.113.24" }}port.modem_disconnected
Заголовок раздела «port.modem_disconnected»Отправляется при отключении модема, обслуживающего порт. last_seen_at содержит время последней зафиксированной активности модема:
{ "id": "66c5f99e2f66247a92846212", "version": "v1", "type": "port.modem_disconnected", "occurred_at": "2026-08-26T09:22:00Z", "data": { "port": { "id": "66bca5147010246361dbe256", "service_id": "service-123", "number": 1042, "status": "disconnected" }, "modem": { "id": "66bca4d67010246361dbe213", "name": "modem-kyiv-01", "last_seen_at": "2026-08-26T09:21:45Z" } }}Проверка подписи
Заголовок раздела «Проверка подписи»LTESocks вычисляет подпись по формуле:
Base64(HMAC-SHA256(webhook_secret, raw_request_body))Результат передается в X-Signature. Храните секрет whsec_... только на сервере и сравнивайте подписи за постоянное время.
Node.js
Заголовок раздела «Node.js»import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(rawBody, receivedSignature, secret) { const expected = createHmac('sha256', secret) .update(rawBody) .digest('base64');
const received = Buffer.from(receivedSignature ?? '', 'base64'); const calculated = Buffer.from(expected, 'base64');
return ( received.length === calculated.length && timingSafeEqual(received, calculated) );}<?php$rawBody = file_get_contents('php://input');$received = $_SERVER['HTTP_X_SIGNATURE'] ?? '';$expected = base64_encode(hash_hmac('sha256', $rawBody, $webhookSecret, true));
if (!hash_equals($expected, $received)) { http_response_code(401); exit;}Официальный SDK
Заголовок раздела «Официальный SDK»Официальные библиотеки сравнивают подпись за постоянное время и декодируют JSON только после успешной проверки:
import { WebhookVerifier } from '@ltesocks/sdk';
const event = await WebhookVerifier.decodeVerifiedJson( rawRequestBody, request.headers.get('x-signature') ?? '', process.env.LTESOCKS_WEBHOOK_SECRET,);import os
from ltesocks_sdk import WebhookVerifier
event = WebhookVerifier.decode_verified_json( raw_body, signature, os.environ["LTESOCKS_WEBHOOK_SECRET"],)<?php
use LTESocks\Webhook\WebhookVerifier;
$event = WebhookVerifier::decodeVerifiedJson( $rawBody, $signature, (string) getenv('LTESOCKS_WEBHOOK_SECRET'),);Безопасная обработка
Заголовок раздела «Безопасная обработка»- Сохраните исходное тело и проверьте
X-Signature. - Отклоните неподдерживаемое значение
version. - Сохраните
idдо выполнения побочных эффектов. - Если
idуже обработан, верните2xxбез повторения действия. - Поставьте событие в очередь для асинхронной обработки.
- Быстро верните ответ
2xx.
LTESocks считает любой ответ 2xx успешным. Тело ответа игнорируется. Перенаправления не выполняются.
Повторы и тайм-ауты
Заголовок раздела «Повторы и тайм-ауты»Доставка может повторяться после ошибок DNS или сети, тайм-аутов, ответов HTTP 408, HTTP 429 и 5xx. Перенаправления, ошибки проверки TLS, нарушения политики endpoint и остальные ответы 4xx не повторяются.
Политика доставки по умолчанию:
| Настройка | Значение |
|---|---|
| Тайм-аут чтения | 5 секунд |
| Тайм-аут записи и подключения | 5 секунд |
| Повторы после первого запроса | 3 |
| Пауза между попытками | 10 секунд |
При настройках по умолчанию одно событие может быть доставлено до четырех раз. Во всех повторах используются одинаковые тело, id события и подпись, поэтому обработчик должен быть идемпотентным.
Требования к endpoint
Заголовок раздела «Требования к endpoint»- Используйте URL с протоколом
httpилиhttps; рекомендуется HTTPS с TLS 1.2 или новее. - Имя хоста должно разрешаться только в публичные IP-адреса.
- Localhost, приватные, link-local, multicast и зарезервированные адреса отклоняются.
- Учетные данные в URL и фрагменты запрещены.
- Не полагайтесь на перенаправления: сразу укажите конечный URL.