Документація / Інтеграція

Вебхуки

Coinetic повідомляє ваш сервер про зміни рахунку POST-запитом. Вебхук — це сигнал «перевір рахунок», а не доказ оплати.

Налаштування

  • Кабінет → «Ключі та вебхуки» → «Додати». URL — лише https:// на публічну адресу та порт 443 (у пісочниці — ще й http://localhost).
  • Секрет endpoint-а показується один раз. До 5 активних endpoint-ів: кожна подія надходить на всі.

Запит

HTTP
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) — історичні, змінювати їх у себе не потрібно.

Перевірка підпису

text
expected = "v1=" + hex(HMAC-SHA256(webhook_secret, X-Webhook-Timestamp + "." + raw_body))
  1. Візьміть сире тіло — байти до парсингу JSON.
  2. Перевірте, що X-Webhook-Timestamp відрізняється від поточного часу не більш ніж на 5 хвилин.
  3. Розбийте X-Webhook-Signature за комою. Підпис правильний, якщо будь-яка частина збігається з очікуваною (порівняння за сталий час).
  4. Не збіглося — відповідайте 401 і нічого не робіть.

Еталон: секрет whsec-0123456789abcdef0123456789abcdef, timestamp 1760000000, тіло {"id":"evt_1","type":"invoice.paid"} → v1=aceeb56215ba09e7a2923d48f89afb8331f422f2d0a8cf60f76fef69fe06a6a4.

Обробка

text
перевірити підпис → дедуплікація за 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 починає підписувати обома секретами.

  1. Додайте новий секрет на сервер (приймайте обидва).
  2. Натисніть «Завершити ротацію» — старий буде видалено.
  3. Приберіть старий секрет із сервера.