Вебхуки
Coinetic повідомляє ваш сервер про зміни рахунку POST-запитом. Вебхук — це сигнал «перевір рахунок», а не доказ оплати.
Налаштування
- Кабінет → «Ключі та вебхуки» → «Додати». URL — лише
https://на публічну адресу та порт 443 (у пісочниці — ще йhttp://localhost). - Секрет endpoint-а показується один раз. До 5 активних endpoint-ів: кожна подія надходить на всі.
Запит
POST /webhooks/coinetic HTTP/1.1
Content-Type: application/json
User-Agent: cryptopay-webhooks/1
X-Webhook-Id: evt_3f9c…
X-Webhook-Timestamp: 1760000000
X-Webhook-Signature: v1=5d1e…
{"id":"evt_3f9c…","type":"invoice.paid","created_at":"2026-10-12T15:04:05Z","livemode":true,"data":{"invoice_id":"inv_x7k2…","order_id":"ORDER-1001","status":"paid","paid_amount":"49990000"}}X-Webhook-Id однаковий під час повторів. Під час ротації секрету в X-Webhook-Signature два підписи через кому. Технічні назви (cryptopay-webhooks/1) — історичні, змінювати їх у себе не потрібно.
Перевірка підпису
expected = "v1=" + hex(HMAC-SHA256(webhook_secret, X-Webhook-Timestamp + "." + raw_body))- Візьміть сире тіло — байти до парсингу JSON.
- Перевірте, що
X-Webhook-Timestampвідрізняється від поточного часу не більш ніж на 5 хвилин. - Розбийте
X-Webhook-Signatureза комою. Підпис правильний, якщо будь-яка частина збігається з очікуваною (порівняння за сталий час). - Не збіглося — відповідайте
401і нічого не робіть.
Еталон: секрет whsec-0123456789abcdef0123456789abcdef, timestamp 1760000000, тіло {"id":"evt_1","type":"invoice.paid"} → v1=aceeb56215ba09e7a2923d48f89afb8331f422f2d0a8cf60f76fef69fe06a6a4.
Обробка
перевірити підпис → дедуплікація за X-Webhook-Id → GET /v1/invoices/{invoice_id}
→ оновити замовлення за статусом з API (видача — один раз) → відповісти 2xx- Дедуплікація. Одна подія може надійти кілька разів. Зберігайте оброблені
X-Webhook-Id; позначку «видано» ставте в тій самій транзакції, що й видачу. - Відповідайте швидко — до 10 секунд. Тривалу роботу передайте в чергу.
- Коди відповіді:
2xx— прийнято;410 Gone— цю доставку не повторювати; будь-який інший код (зокрема3xx— редиректи не виконуються) або тайм-аут — повтор. - Ігноруйте незнайомі поля й типи подій — список зростатиме.
Готові обробники чотирма мовами — у швидкому старті.
Повтори
10 с → 30 с → 2 хв → 10 хв → 30 хв → 1 год → 3 год ×7 → 1 год, з невеликим розкидом. Остання спроба — приблизно через добу. Невдалу доставку можна надіслати знову: кабінет → «Вебхуки» → «Надіслати повторно».
Порядок
Події одного рахунку доставляються на endpoint по черзі: наступна не надсилається, поки попередня доставка ще чекає на повтор. Хоч би як вона завершилася — успішно чи ні, — далі йдуть наступні. Тому спирайтеся на статус із GET /v1/invoices/{id}, а не на послідовність подій. Події різних рахунків незалежні.
Типи подій
| Подія | Коли |
|---|---|
invoice.detected | Платіж видно в мережі |
invoice.confirming | Платіж у блоці, тривають підтвердження |
invoice.paid | Оплачено й підтверджено — можна видавати (після повторної перевірки). data.late: true — стейблкоїн надійшов після терміну й зарахований автоматично |
invoice.overpaid | Оплачено з надлишком |
invoice.underpaid | Підтверджено менше, ніж потрібно |
invoice.awaiting_payment | Рахунок знову чекає на оплату (наприклад, після реоргу єдиного платежу) |
invoice.expired | Термін минув без оплати |
invoice.late_payment | Оплата волатильним активом після терміну |
invoice.manual_review | Платіж на перевірці AML |
invoice.payment_held | Платіж затримано AML (карантин) |
invoice.reorged | Блок із платежем відкотився, статус перераховано (наприклад, paid → confirming) |
invoice.payment_after_close | Платіж надійшов на вже закритий рахунок: замовлення не оплачує, доступний для повернення |
invoice.cancelled | Рахунок закрито без оплати виконанням повернення |
refund.sent | Повернення виконано, у data.refund — сума, адреса й tx_hash |
Події білінгу (billing.*) стосуються рахунків на комісію платформи: виставлено, оплачено, прострочено, призупинення та його зняття.
invoice.reorgedРеорг після paid трапляється рідко, але буває. Якщо товар видається миттєво — підпишіться на цю подію та передавайте такі випадки в підтримку.Ротація секрету
Кабінет → «Змінити секрет»: Coinetic починає підписувати обома секретами.
- Додайте новий секрет на сервер (приймайте обидва).
- Натисніть «Завершити ротацію» — старий буде видалено.
- Приберіть старий секрет із сервера.