Webhook
Подписанные доставки событий: доступные события, проверка X-LinkProfit-Signature на JavaScript и Python, повторы и состояние отказа.
Обновлено 13 августа 2026 г.
Webhook присылают события на ваш эндпоинт POST-запросами в JSON — без опроса.
Регистрируйте эндпоинты в панели (Настройки → Webhook) или через
POST /v1/webhooks; секрет подписи показывается один раз при создании.
События
| Событие | Когда срабатывает | Кому доступно |
|---|---|---|
| link.created / link.updated / link.deleted | Ссылка изменилась — через панель, API или пакетный импорт | эндпоинтам рабочего пространства и партнёра |
| domain.pending_ssl | DNS подтверждён, сертификат выпускается | рабочему пространству и партнёру |
| domain.activated | Домен обслуживает трафик | рабочему пространству и партнёру |
| domain.error | Подготовка не удалась; подробности внутри | рабочему пространству и партнёру |
| click.threshold | 80 % / 100 % месячного лимита отслеживаемых кликов | рабочему пространству и партнёру |
| conversion.created | Конверсия записана: заказ, регистрация или своя цель, отнесённая к клику | рабочему пространству и партнёру |
| workspace.subscribed | Клиент оплатил первый счёт подписки | только партнёру |
| workspace.past_due | Платёж клиента не прошёл | только партнёру |
| workspace.suspended | Клиент приостановлен (по напоминаниям об оплате или вручную) | только партнёру |
| payment.succeeded | Платёж клиента прошёл, с разбивкой по комиссиям | только партнёру |
| payment.refunded | Платёж возвращён | только партнёру |
Доставка
POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-LinkProfit-Event: link.created
X-LinkProfit-Delivery: dlv_8Yq2…
X-LinkProfit-Signature: t=1755081600,v1=5f8a2c…
{
"id": "dlv_8Yq2…",
"type": "link.created",
"created_at": "2026-08-13T10:00:00.000Z",
"data": { "id": "lnk_…", "domain": "go.your-brand.com", "slug": "x7f2q1z", "url": "https://example.com" }
}
Ответьте любым 2xx в течение 10 секунд. Всё остальное, включая таймаут,
считается неудачей и планирует повтор. Доставки могут приходить не по порядку
и, изредка, дважды: дедуплицируйте по id.
Проверка подписи
Подпись — это HMAC-SHA256 от `${t}.${rawBody}` с секретом вашего эндпоинта,
в шестнадцатеричной кодировке. Всегда проверяйте по сырому телу запроса, до
любого разбора JSON, и отклоняйте отметки времени старше 5 минут.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifySignature(secret, rawBody, header, toleranceSeconds = 300) {
const parts = Object.fromEntries(
header.split(",").map((piece) => piece.split("=", 2)),
);
if (!parts.t || !parts.v1) return false;
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > toleranceSeconds) return false;
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1);
return a.length === b.length && timingSafeEqual(a, b);
}
import hashlib
import hmac
import time
def verify_signature(secret: str, raw_body: bytes, header: str, tolerance: int = 300) -> bool:
parts = dict(piece.split("=", 1) for piece in header.split(",") if "=" in piece)
timestamp, signature = parts.get("t"), parts.get("v1")
if not timestamp or not signature:
return False
if abs(time.time() - int(timestamp)) > tolerance:
return False
expected = hmac.new(
secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Повторы и состояние отказа
Первая попытка выполняется сразу. Неудачи повторяются по фиксированному графику:
1 мин → 5 мин → 30 мин → 2 ч → 12 ч. После пятого повтора эндпоинт
помечается failing, перестаёт получать новые события, а владельцу уходит письмо.
Почините эндпоинт, а затем снова включите его в панели или через
PATCH /v1/webhooks/{id} с {"status": "active"}. Пропущенные события автоматически
не переигрываются — журнал доставок (GET /v1/webhooks/{id}/deliveries
или панель) показывает каждую полезную нагрузку, чтобы вы могли сверить данные.
Успешная доставка сбрасывает череду неудач.
Тестирование
Кнопка Отправить тест (или POST /v1/webhooks/{id}/test) доставляет настоящее
подписанное событие с "data": { "test": true } через тот же конвейер, что и
продакшен-события, — журнал доставок показывает ответ вашего эндпоинта.