Вебхуки¶
Замість опитування — підпишіться на події, і HugeProfit POST-итиме їх на ваш URL у реальному часі. Доставки зберігаються в надійній черзі, підписуються та ретраяться при збої.
Як це працює¶
- Ви створюєте підписку: подія + цільовий URL (+ опційний секрет).
- Коли подія стається будь-де в системі, ми ставимо в чергу доставку.
- Диспетчер POST-ить підписане тіло на ваш URL.
- На будь-яку не-2xx / мережеву помилку — ретрай із backoff, до 5 спроб.
Каталог подій¶
GET /webhooks/events повертає актуальний список. Поточні події:
| Подія | Спрацьовує коли |
|---|---|
sms |
клієнту надіслано SMS |
order_create |
створено продаж |
order_update |
змінено продаж: відредаговано, змінився статус (зокрема від відстеження доставки — посилка прибула, отримана, повертається), додано ТТН |
order_delete |
видалено продаж |
product_update |
створено або оновлено товар |
client_update |
створено або оновлено клієнта |
stock_update |
змінився залишок товару |
order_* = продажі
Події order_* спрацьовують на життєвому циклі продажу (/sales), а не на замовленнях
із маркетплейсів (/orders).
Підписки¶
| Метод | Шлях | Scope |
|---|---|---|
GET |
/webhooks |
webhooks:read |
POST |
/webhooks |
webhooks:write |
GET |
/webhooks/{id} |
webhooks:read |
PUT |
/webhooks/{id} |
webhooks:write |
DELETE |
/webhooks/{id} |
webhooks:write |
GET |
/webhooks/events |
webhooks:read |
GET |
/webhooks/deliveries |
webhooks:read |
POST |
/webhooks/test |
webhooks:write |
Створення:
curl -X POST https://crm.h-profit.com/bapi-v2/webhooks \
-H "Authorization: hp_live_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{ "event": "stock_update", "url": "https://yoursite.com/hooks/stock",
"description": "синк залишків" }'
Відповідь повертає згенерований secret один раз — збережіть його, він потрібен для
перевірки підпису. Пізніші списки показують лише замаскований secret_hint.
{
"id": 5, "event": "stock_update", "url": "https://yoursite.com/hooks/stock",
"is_active": true, "description": "синк залишків",
"has_secret": true, "secret_hint": "whsec_0L2T1…",
"secret": "whsec_0L2T1ARi6Ug8C7VBea-e0NJ-…", "created_at": 1784556220
}
Можна передати власний secret, кастомні headers (об'єкт) та is_active. PUT оновлює
будь-що з цього; передача secret ротує його.
url має бути http(s)-адресою в публічному інтернеті: localhost, приватні мережі
(10.*, 192.168.*, …) і link-local адреси відхиляються з 422; домен, що резолвиться в таку
адресу, не пройде під час доставки. Редиректи не виконуються — 3xx рахується невдалою спробою.
Тіло доставки¶
Кожна доставка POST-ить таке JSON-тіло:
{
"id": "b3f1…-uuid",
"event": "stock_update",
"created_at": 1784556220,
"data": { "products": [ { "pid": 123, "mid": 8562, "stock": 7, "price": "10.00" } ] }
}
Із заголовками:
| Заголовок | Значення |
|---|---|
X-GP-Event |
назва події |
X-GP-Delivery |
UUID доставки (також data.id) — для ідемпотентності |
X-GP-Signature |
підпис (якщо підписка має секрет) |
Форма data по подіях: stock_update → { products: [...] }; order_* →
{ id, action, order_number, status, tracking_number, external_id }; client_update → { id, action, phone, name };
product_update → { id, action, name } або { action: "imported", count, source };
sms → { phone, order_id, order_status, message }.
action у order_update: status_changed (з previous_status) або updated; після редагування
продаж має новий id, а previous_id — старий. external_id — ваш номер замовлення, переданий під
час створення (null, якщо не передавали):
{ "id": 4605, "action": "status_changed", "order_number": "20072602", "status": "arrived",
"previous_status": "delivering", "tracking_number": "20450000000001", "external_id": "site-1001" }
Перевірка підпису¶
Якщо підписка має секрет, ми підписуємо сире тіло:
v1 — це HMAC_SHA256(secret, "<t>.<raw_body>"). Щоб перевірити:
- Розберіть
tтаv1із заголовка. - Перерахуйте
HMAC_SHA256(secret, t + "." + raw_request_body). - Порівняйте в constant time; відхиліть, якщо відрізняється.
- Відхиліть, якщо
tстаріший за ~5 хвилин (захист від replay).
import hmac, hashlib, time
def verify(secret, raw_body, header, tolerance=300):
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts["t"])
if abs(time.time() - t) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{t}.{raw_body}".encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
Ретраї та backoff¶
Відповідайте 2xx для підтвердження. Будь-який інший статус (або таймаут/мережева помилка) запускає ретрай:
| Спроба | Пауза до наступної |
|---|---|
| 1 → 2 | 1 хвилина |
| 2 → 3 | 5 хвилин |
| 3 → 4 | 15 хвилин |
| 4 → 5 | 30 хвилин |
| після 5 | позначається dead |
Таймаут доставки — 15 секунд. Доставка — at-least-once — дедуплікуйте за X-GP-Delivery.
Журнал доставок¶
GET /webhooks/deliveries повертає історію доставок (фільтри webhook_id, status):
{
"id": "b3f1…-uuid", "webhook_id": 5, "event": "stock_update",
"status": "success", "attempt": 1, "max_attempts": 5,
"response_code": 200, "error": null, "duration_ms": 84,
"next_retry_at": null, "created_at": "2026-07-20T…"
}
status — одне з pending, success, failed (буде ретрай), dead (здалися).
Тестування ендпоінта¶
POST /webhooks/test доставляє зразкове тіло синхронно і повертає сирий результат — зручно
під час налаштування приймача. Передайте наявний webhook_id або разовий url (+ опційно
secret, event, data):
curl -X POST https://crm.h-profit.com/bapi-v2/webhooks/test \
-H "Authorization: hp_live_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{ "webhook_id": 5, "data": { "ping": 1 } }'
{ "ok": true, "response_code": 200, "response_body": "…", "duration_ms": 84,
"sent_signature": "t=…,v1=…", "sent_body": { /* конверт, який ми надіслали */ } }
Найкращі практики¶
- Перевіряйте підпис на кожному запиті.
- Повертайте
2xxшвидко (до 15с); важку роботу робіть асинхронно. - Дедуплікуйте за
X-GP-Delivery— та сама подія може прийти кілька разів. - Нова підписка може стати активною до ~30с на всіх продюсерах.