Вебхуки: події на ваш сервер
Підписані вебхуки та REST hooks reactive.chat: події, заголовки, тіло, перевірка HMAC-SHA256, повторні спроби, тайм-аути, деактивація та приклади перевірки PHP, Node й Python.
Вебхуки повідомляють серверу про події в чаті: нову розмову, нове повідомлення, передачу команді, оцінку. Є два способи:
- Підписаний вебхук — одна цільова адреса на робочий простір, налаштовується в обліковому записі, кожна доставка підписана HMAC-SHA256. Належний спосіб для власних систем.
- REST hooks — цілі, які інструмент автоматизації (Zapier, Make, n8n) сам підписує й відписує через серверний API.
Події
- conversation.created — створено розмову. Канал у
channel(web,whatsapp,email…). - message.created — збережено повідомлення (від відвідувача, асистента, оператора або системи).
- handoff.requested — розмову потрібно передати людині; із
reasonтаtarget. - csat.submitted — відвідувач оцінив розмову;
score(1або-1) іcomment(із замаскованими персональними даними). - fehlerfall.erstellt — на сайті виявлено нову помилку JavaScript (див. Посібник).
Розмови з пошуку на сайті (Smart Answer) створюють події лише після того, як стають видимими як чат.
Налаштування підписаного вебхука
В обліковому записі в розділі Налаштування → Інтеграції → Вебхуки (право: керувати інтеграціями):
- URL —
https://, щонайбільше 1000 символів, публічно доступна. Одна адреса на робочий простір. - Події — вибір; якщо нічого не вибрано, це означає всі.
- Секрет підпису — показаний на сторінці (64 шістнадцяткові символи). Створити заново робить попередній недійсним негайно; сплануйте перехід так, щоб одержувач короткий час приймав обидва.
Під час збереження тестовий виклик не надсилається. Після ввімкнення до початку надходження подій може минути близько 15 секунд; попередні події не доставляються заднім числом.
Доставка
POST /rc-webhook HTTP/1.1
Host: hooks.your-company.com
Content-Type: application/json; charset=utf-8
User-Agent: reactive.chat-webhook/1.0
X-RC-Event: csat.submitted
X-RC-Delivery: 01JAB3C4D5E6F7G8H9JKMNPQRS
X-RC-Timestamp: 1792503600
X-RC-Signature: sha256=3f0a1c...
{"id":"01JAB3C4D5E6F7G8H9JKMNPQRS","event":"csat.submitted","ts":1792503600,"site_key":"ABCDEFGHJKLMNPQRSTUVWX12","conversation_id":"01JAB2...","session_id":"s_...","visitor_id":"v_...","data":{"score":5,"comment":"Very helpful"}}
Заголовки:
- X-RC-Event — назва події.
- X-RC-Delivery — ID доставки; не змінюється під час повторних спроб. Використовуйте для визначення дублікатів.
- X-RC-Timestamp — секунди Unix.
- X-RC-Signature —
sha256=+hex(HMAC_SHA256(secret, X-RC-Timestamp + "." + raw_body)). Ключ — сам показаний шістнадцятковий рядок.
Тіло:
- id (рядок) — те саме, що
X-RC-Delivery. - event (рядок).
- ts (ціле число) — секунди Unix.
- site_key, conversation_id, session_id, visitor_id (рядок або
null). - data (об’єкт) — дані конкретної події. Для
fehlerfall.erstellt:fall_id,project_id,signatur,meldung,datei,zeile,spalte,seite,browser,os,stack,erste_ms,url(посилання на помилку в обліковому записі). Дляmessage.created:messageзid,seq,kind,direction,author_type,author_name(лише для оператора й асистента),via,body(замасковано на сервері),redacted,ts(мілісекунди). Дляhandoff.requested:reasonтаtarget. Дляcsat.submitted:scoreіcomment. Дляconversation.created:channel.
Перевірка підпису
Перевіряйте перед будь-якою обробкою: позначка часу не старша за 300 секунд, підпис за сирим тілом, порівняння за сталий час.
PHP:
<?php
$geheim = getenv('RC_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_RC_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_RC_SIGNATURE'] ?? '';
if (!ctype_digit($ts) || abs(time() - (int) $ts) > 300) { http_response_code(401); exit; }
$soll = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $geheim);
if (!hash_equals($soll, $sig)) { http_response_code(401); exit; }
$ereignis = json_decode($body, true);
// detect duplicates: remember $ereignis['id']
http_response_code(204);
Node.js (Express):
const crypto = require('crypto');
app.post('/rc-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-RC-Timestamp') || '';
const sig = req.get('X-RC-Signature') || '';
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const soll = 'sha256=' + crypto.createHmac('sha256', process.env.RC_WEBHOOK_SECRET)
.update(ts + '.' + req.body.toString('utf8')).digest('hex');
if (sig.length !== soll.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(soll))) {
return res.sendStatus(401);
}
const ereignis = JSON.parse(req.body.toString('utf8'));
res.sendStatus(204);
verarbeiteSpaeter(ereignis); // respond quickly, work afterwards
});
Python (Flask):
import hmac, hashlib, os, time
from flask import request, abort
@app.post("/rc-webhook")
def rc_webhook():
ts = request.headers.get("X-RC-Timestamp", "")
sig = request.headers.get("X-RC-Signature", "")
body = request.get_data() # raw bytes
if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
abort(401)
soll = "sha256=" + hmac.new(os.environ["RC_WEBHOOK_SECRET"].encode(),
ts.encode() + b"." + body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(soll, sig):
abort(401)
return "", 204
Відповіді, повторні спроби, деактивація
Відповідайте швидко кодом 2xx і обробляйте після цього. Тайм-аути: 4 секунди на встановлення з’єднання, загалом 10 секунд. Перенаправлення не виконуються.
- 2xx — доставлено.
- 408, 429, 5xx, тайм-аут, помилка мережі — повтор через 1 с, 5 с, 25 с, 125 с і 625 с (загалом до шести спроб), потім відкидається.
- 410 Gone — інтеграція деактивується. Використовуйте 410, лише якщо справді більше не хочете вебхуків.
- інші 4xx — без повтору.
Події, старші за годину, більше не доставляються. Якщо помилки накопичуються (5 за 60 секунд), доставка до цілі призупиняється на 30 секунд; потім завдання повторюються. Чат ніколи не чекає на вебхук.
Порядок доставки не гарантований. За потреби сортуйте за ts або seq повідомлень з API.
REST hooks (Zapier, Make, n8n)
Інструменти автоматизації самостійно підписують свої цілі через серверний API. Цим можна користуватися й безпосередньо:
curl -X POST https://reactive.chat/v1/hooks \
-H "Authorization: Bearer rc_live_..." \
-H "Content-Type: application/json" \
-d '{"event":"message.created","target_url":"https://hooks.your-company.com/rc","source":"n8n"}'
- POST /v1/hooks — права із дозволом запису.
event(одна з подій вище),target_url(https://, щонайбільше 500 символів, публічна),source(zapier,makeабоn8n, стандартноzapier). Відповідь 201 зid. Однакове поєднання події й цілі не створюється двічі. Щонайбільше 200 підписок на робочий простір. - GET /v1/hooks — список із
id,event,target_url,source,failures,created_at,last_ok_at. - DELETE /v1/hooks/{id} — відписатися.
Доставка REST hook:
POST https://hooks.your-company.com/rc
Content-Type: application/json
User-Agent: reactive.chat-n8n/1.0
X-RC-Event: message.created
X-RC-Delivery: 01JAB3...
{"event":"message.created","delivery_id":"01JAB3...","data":{"name":"message.created","ts":1792503600123,"site_key":"...","conversation_id":"...","session_id":"...","visitor_id":"...","message":{"id":"...","seq":7,"kind":"text","direction":"in","author_type":"bot","author_name":"Assistant","via":null,"body":"…","redacted":false,"ts":1792503600120}}}
- Без підпису. Використовуйте цільову адресу, яку важко вгадати, та перевіряйте дублікати через
X-RC-Delivery. Для власних систем кращий спосіб — підписаний вебхук. data— повна подія: додатковоworkspace_id,delivery_idтаattempt(номер спроби). Тутdata.tsу мілісекундах.dataподіїmessage.createdміститьmessageізid,seq,kind,direction,author_type,author_name(лише для оператора й асистента),via,body(замасковано на сервері),redacted,ts.handoff.requestedміститьreasonіtarget,csat.submitted—scoreіcomment,conversation.created—channel.- 410 відписує лише цю одну підписку. Hooks відкликаного ключа API більше не обслуговуються.
- Наразі для доставки відповідна інтеграція (Zapier, Make або n8n) має бути ввімкнена в робочому просторі в розділі Інтеграції.
Чого немає
- Немає вхідного вебхука, через який сервер додає повідомлення відвідувачів у розмову. Відповіді від імені команди надсилаються через серверний API або MCP.
- Немає перехідного періоду під час оновлення секрету підпису.
- Немає події видалення розмови.
Далі: Серверний API
Оновлено: