Вебхуки
Получайте HTTP-уведомления в реальном времени о событиях в магазине продавца. Все доставки подписаны HMAC-SHA256 и включают автоматические повторные попытки.
Создание вебхука
Зарегистрируйте эндпоинт вебхука, используя токен доступа вашего приложения:
curl -X POST https://api.bazex.co/webhooks \
-H "Authorization: Bearer fbat_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/bazex",
"events": ["order.created", "order.status_changed", "product.updated"],
"description": "Main webhook endpoint"
}'{
"id": "clx1webhook123",
"url": "https://your-app.com/webhooks/bazex",
"secret": "whsec_a1b2c3d4e5f6a7b8c9d0e1f2",
"events": ["order.created", "order.status_changed", "product.updated"],
"isActive": true,
"createdAt": "2026-02-20T10:00:00.000Z"
}Сохраните секретный ключ
secret возвращается только один раз при создании. Сохраните его в надёжном месте — он понадобится для проверки подписей вебхуков.Каталог событий
Вы получаете только те события, на которые у вашего приложения есть соответствующие scopes.
Заказы
| Событие | Описание |
|---|---|
| order.created | Новый заказ создан |
| order.status_changed | Статус заказа обновлён |
| order.delivered | Заказ доставлен |
| order.cancelled | Заказ отменён |
Платежи
| Событие | Описание |
|---|---|
| payment.completed | Платёж успешно обработан |
| payment.expired | Срок платежа истёк |
Товары
| Событие | Описание |
|---|---|
| product.created | Новый товар добавлен |
| product.updated | Данные товара изменены |
| product.deleted | Товар удалён |
Складской учёт
| Событие | Описание |
|---|---|
| product.out_of_stock | Товар закончился на складе |
| product.low_stock | Остаток товара ниже порога |
| product.back_in_stock | Товар снова в наличии |
Отзывы
| Событие | Описание |
|---|---|
| review.created | Новый отзыв оставлен |
| review.deleted | Отзыв удалён |
Жизненный цикл
| Событие | Описание |
|---|---|
| business.data_erasure | Продавец удалил приложение — удалите сохранённые данные |
Формат данных
Каждая доставка вебхука — это POST-запрос с JSON-телом:
{
"event": "order.created",
"timestamp": "2026-02-20T10:30:45.123Z",
"webhookId": "clx1webhook123",
"businessId": "clx1business456",
"data": {
"orderId": "clx1order789",
"orderNumber": "1042",
"amount": 1590,
"deliveryFee": 200,
"deliveryMethod": "DELIVERY",
"paymentMethod": "CARD",
"isGuest": false,
"createdAt": "2026-02-20T10:30:45.000Z"
}
}Заголовки доставки
| Заголовок | Описание |
|---|---|
| X-Webhook-Id | ID зарегистрированного вебхука |
| X-Webhook-Event | Тип события (например, order.created) |
| X-Webhook-Signature | Подпись HMAC-SHA256 (sha256=<hex>) |
| X-Webhook-Timestamp | Unix-время (в секундах) отправки доставки |
| X-Bazex-Event-Id | Уникальный ID доставки — используйте для идемпотентности/дедупликации |
| User-Agent | Bazex-Webhooks/1.0 |
Проверка подписи
Всегда проверяйте подпись перед обработкой вебхука. Подпись вычисляется следующим образом:
signature = HMAC-SHA256(secret, "${timestamp}.${rawBody}")С использованием @bazex/app-sdk:
import { verifySignature, isTimestampFresh } from '@bazex/app-sdk';
app.post('/webhooks/bazex', (req, res) => {
const signature = req.headers['x-webhook-signature'] as string;
const timestamp = parseInt(req.headers['x-webhook-timestamp'] as string);
const rawBody = JSON.stringify(req.body);
// Verify signature (constant-time comparison)
if (!verifySignature(signature, timestamp, rawBody, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Check timestamp freshness (default: 5 min window)
if (!isTimestampFresh(timestamp)) {
return res.status(401).send('Timestamp too old');
}
// Process the event
const { event, data } = req.body;
console.log(`Received ${event}`, data);
// Respond quickly — process async
res.status(200).send('OK');
});Или вручную на любом языке:
const crypto = require('crypto');
function verify(signature, timestamp, body, secret) {
const payload = `${timestamp}.${body}`;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}Политика повторных попыток
Если ваш эндпоинт возвращает статус, отличный от 2xx, или не отвечает в течение 10 секунд, Bazex повторяет доставку с экспоненциальным увеличением задержки:
| Попытка | Задержка |
|---|---|
| 1-я повторная | 30 секунд |
| 2-я повторная | 2 минуты |
| 3-я повторная | 8 минут |
| 4-я повторная | 32 минуты |
| 5-я повторная (последняя) | 2 часа |
Автоматическое отключение
Идемпотентность
Заголовок X-Bazex-Event-Id содержит уникальный ID доставки, который остаётся одинаковым при повторных попытках. Используйте его для дедупликации событий:
app.post('/webhooks/bazex', async (req, res) => {
const eventId = req.headers['x-bazex-event-id'] as string;
// Check if already processed
if (await db.processedEvents.findUnique({ where: { id: eventId } })) {
return res.status(200).send('Already processed');
}
// Process event...
await db.processedEvents.create({ data: { id: eventId } });
res.status(200).send('OK');
});Тестирование вебхуков
Отправьте тестовое событие на ваш эндпоинт вебхука:
curl -X POST https://api.bazex.co/webhooks/WEBHOOK_ID/test \
-H "Authorization: Bearer fbat_..."Будет отправлено событие webhook.test с тестовым payload. В ответе будут указаны HTTP-статус и время выполнения доставки.
Обязанность по удалению данных
Когда продавец удаляет ваше приложение, Bazex отправляет вебхук business.data_erasure через 48 часов после удаления. Ваше приложение обязано удалить все сохранённые данные продавца при получении этого события.
{
"event": "business.data_erasure",
"timestamp": "2026-02-22T12:00:00.000Z",
"webhookId": "clx1webhook123",
"businessId": "clx1business456",
"data": {
"appId": "clx1app789",
"businessId": "clx1business456",
"uninstalledAt": "2026-02-20T12:00:00.000Z"
}
}Всегда доставляется
- Scope не требуется — все приложения с URL вебхука получают это событие
- 48-часовая задержка даёт время для завершения текущих операций перед очисткой
- Верните статус 2xx для подтверждения — иначе будут повторные попытки по стандартному расписанию
- Несоблюдение требования по удалению данных может привести к удалению приложения из маркетплейса
Лучшие практики
- Отвечайте быстро — возвращайте 200 в течение нескольких секунд, обрабатывайте событие асинхронно
- Всегда проверяйте подпись — никогда не доверяйте непроверенным данным
- Используйте идемпотентность — сохраняйте
X-Bazex-Event-Idдля предотвращения повторной обработки - Используйте HTTPS — URL вебхуков в продакшене должны использовать HTTPS
- Обрабатывайте повторы корректно — ваш эндпоинт может получить одно и то же событие несколько раз
- Обрабатывайте удаление данных — реализуйте обработчик
business.data_erasureдля удаления данных продавца при деинсталляции