Wie können wir helfen?

Schreib uns kurz, worum es geht - wir melden uns per E-Mail.

Diese Seite ist durch reCAPTCHA geschützt. Es gelten die Datenschutzerklärung und die Nutzungsbedingungen von Google.
Zur Startseite

Webhooks: Ereignisse an deinen Server

Signierte Webhooks und REST-Hooks von reactive.chat – Ereignisse, Kopfzeilen, Rumpf, Signaturprüfung mit HMAC-SHA256, Wiederholungen, Zeitlimits, Deaktivierung und Beispiele zum Prüfen in PHP, Node und Python.

Webhooks melden deinem Server, was im Chat passiert: ein neues Gespräch, eine neue Nachricht, eine Übergabe an das Team, eine Bewertung. Es gibt zwei Wege:

Ereignisse

Gespräche aus der Website-Suche (Smart Answer) lösen erst dann Ereignisse aus, wenn sie als Chat sichtbar werden.

Signierten Webhook einrichten

Im Konto unter Einstellungen → Integrationen → Webhooks (Recht: Integrationen verwalten):

Beim Speichern wird kein Testaufruf geschickt. Nach dem Einschalten können bis zu etwa 15 Sekunden vergehen, bis Ereignisse fließen; Ereignisse von vor dem Einschalten werden nicht nachgeliefert.

Die Zustellung

POST /rc-webhook HTTP/1.1
Host: hooks.deine-firma.de
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":"Sehr hilfreich"}}

Kopfzeilen:

Rumpf:

Signatur prüfen

Prüfe vor jeder Verarbeitung: Zeitstempel höchstens 300 Sekunden alt, Signatur über den rohen Body, Vergleich zeitkonstant.

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);
// Doppelte erkennen: $ereignis['id'] merken
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);   // schnell antworten, danach arbeiten
});

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()                      # rohe 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

Antworten, Wiederholungen, Deaktivierung

Antworte schnell mit einem 2xx und verarbeite danach. Zeitlimits: 4 Sekunden für den Verbindungsaufbau, 10 Sekunden gesamt. Weiterleitungen werden nicht verfolgt.

Ereignisse, die älter als eine Stunde sind, werden nicht mehr zugestellt. Häufen sich Fehler (5 in 60 Sekunden), pausiert die Zustellung an dein Ziel für 30 Sekunden; die Aufträge werden danach wiederholt. Ein Chat wartet nie auf deinen Webhook.

Die Reihenfolge der Zustellungen ist nicht garantiert. Sortiere bei Bedarf nach ts bzw. nach seq der Nachrichten aus der API.

REST-Hooks (Zapier, Make, n8n)

Automatisierungswerkzeuge melden ihre Ziele selbst über die Server-API an. Du kannst das auch direkt nutzen:

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.deine-firma.de/rc","source":"n8n"}'

Zustellung eines REST-Hooks:

POST https://hooks.deine-firma.de/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":"Assistent","via":null,"body":"…","redacted":false,"ts":1792503600120}}}

Was es nicht gibt

Weiter: Server-API

Stand: