Вебхуки
Укажите URL и секрет вебхука во вкладке Вебхуки интеграции в дашборде и включите отправку. Ваш сервер должен принимать POST-запросы с JSON.
Shop API отправляет только окончательные результаты:
| Событие | Статус | Значение |
|---|---|---|
order.completed | completed | Покупка успешно выполнена |
order.refunded | refunded | Покупка не выполнена, списанная сумма возвращена |
Для processing, review, проверки получателя и нехватки баланса отдельного вебхука нет. Telegram-уведомления настраиваются отдельно.
Тело запроса
{
"event": "order.completed",
"timestamp": "2026-09-26T12:00:05.000Z",
"data": {
"order_id": 125,
"partner_order_id": "order-456",
"api_user_id": "customer-789",
"module": "codes",
"status": "completed",
"amount_usd": "0.9800",
"currency": "USD",
"codes": [
{"content": "EXAMPLE-CODE"}
]
}
}
| Поле | Описание |
|---|---|
event | order.completed или order.refunded |
timestamp | Время формирования вебхука в UTC, ISO 8601; не дата создания заказа |
data.order_id | ID заказа AdaptGroup |
data.partner_order_id | Ваш ID заказа или null |
data.api_user_id | Строковый ID вашего клиента |
data.module | stars, tg_premium, topups или codes |
data.status | Окончательный статус заказа |
data.amount_usd | Списанная/возвращённая сумма десятичной строкой |
data.currency | Всегда USD |
data.codes | Выданные коды только для завершённого заказа codes; иначе [] |
У кода могут присутствовать content, number и/или pin. Включаются только имеющиеся значения.
Пример возврата:
{
"event": "order.refunded",
"timestamp": "2026-09-26T12:00:05.000Z",
"data": {
"order_id": 125,
"partner_order_id": "order-456",
"api_user_id": "customer-789",
"module": "codes",
"status": "refunded",
"amount_usd": "0.9800",
"currency": "USD",
"codes": []
}
}
Проверка подписи
Заголовок X-Webhook-Signature содержит HMAC-SHA256 от исходных байтов тела запроса с вашим секретом вебхука. Подпись — шестнадцатеричная строка в нижнем регистре.
Сам секрет не передаётся ни в заголовке, ни в JSON. Это отдельное значение, не API-ключ.
Проверяйте исходное тело до разбора JSON. Повторная сериализация JSON меняет байты и может сделать подпись неверной.
const crypto = require('node:crypto');
function verifySignature(rawBody, secret, signature) {
if (typeof signature !== 'string' || !/^[a-f0-9]{64}$/.test(signature)) {
return false;
}
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest();
return crypto.timingSafeEqual(expected, Buffer.from(signature, 'hex'));
}
rawBody — исходный Buffer, полученный HTTP-сервером, до преобразования JSON-парсером.
Подтверждение и повторная доставка
- Проверьте подпись.
- Сопоставьте
data.order_idсо своим заказом. - Сохраните и примените окончательный результат один раз.
- Ответьте HTTP 200 или 201 после принятия события.
Тело ответа не требуется. Другие статусы, включая 204, не подтверждают доставку. Отправитель ожидает HTTP-запрос до 10 секунд.
Событие может приходить повторно. По интеграции, data.order_id и event определяйте уже обработанный результат. Не выдавайте товар и не зачисляйте возврат повторно. Такая обработка повторов вебхука не превращает повторные вызовы /orders/create в одну покупку.
Попытки доставки
После принятия события сервисом доставки неуспешная отправка повторяется:
| Попытка | Задержка после предыдущей неудачной попытки |
|---|---|
| 1 | Сразу |
| 2 | 1 минута |
| 3 | 2 минуты |
| 4 | 5 минут |
| 5 | 10 минут |
| 6 | 15 минут |
| 7 | 30 минут |
| 8 | 1 час |
| 9 | 2 часа |
| 10 | 2 часа |
Вебхук не гарантирует, что каждый результат дойдёт до вашего сервера. Если он не пришёл, получите сохранённый результат через Статус заказа. Повторная покупка не является способом восстановить доставку результата.