Skip to main content

Webhooks

TapToChat kann bei jedem Ereignis eine HTTPS-Anfrage an einen Server senden: eine neue Unterhaltung, eine Nachricht, eine Zuweisung. Jede Anfrage ist signiert, damit ihre Herkunft überprüfbar ist.

Einen Webhook einrichten

Webhooks gehören zum Pro-Tarif. Inhaber und Admins verwalten sie in den Einstellungen.

  1. Einstellungen → Webhooks öffnen und „Webhook hinzufügen“ wählen.
  2. Einen Namen und die https-URL angeben, die die Ereignisse empfangen soll.
  3. Die zu sendenden Ereignisse auswählen.
  4. Das Signatur-Secret kopieren. Es wird nur einmal angezeigt und lässt sich später erneuern.
Einstellungen → Webhooks öffnen

Ereignisse

Jeder Webhook erhält nur die Ereignisse, die er abonniert hat.

EreignisGesendet, wenn
conversation.createdein Besucher eine Unterhaltung beginnt, auf jedem Kanal.
conversation.assignedeine Unterhaltung einem Agenten zugewiesen wird.
conversation.closedeine Unterhaltung geschlossen wird.
message.createdeine Nachricht gespeichert wird: von einem Besucher, einem Agenten oder als automatische Antwort.
tag.addedeiner Unterhaltung ein Tag hinzugefügt wird.
note.createdein Agent eine interne Notiz hinzufügt oder einen Befehl wie /summary ausführt, dessen Ergebnis als Notiz gespeichert wird (kind command_result).
integration.connectedeine Integration verbunden wird.
integration.disconnectedeine Integration getrennt wird.
integration.errordie Synchronisierung einer Integration fehlschlägt.
webhook.testin den Einstellungen „Testereignis senden“ gewählt wird. Sonst nie.

Inhalt

Jede Anfrage ist ein POST mit einem JSON-Body in stets derselben Hülle:

{
  "id": "6f1c2b0e-8a7d-4c1e-9b3a-2d5e7f9a1c4b",
  "event": "message.created",
  "created_at": "2026-10-01T09:30:00.000Z",
  "organization_id": "0c9a1f4e-3b2d-4e5f-8a6b-7c8d9e0f1a2b",
  "data": {
    "message": {
      "id": "a1b2c3d4-…",
      "conversation_id": "e5f6a7b8-…",
      "sender_type": "visitor",
      "sender_id": null,
      "content": "Hello, is anyone there?",
      "channel": "web",
      "created_at": "2026-10-01T09:30:00.000Z"
    },
    "conversation": { "id": "e5f6a7b8-…", "status": "open", "visitor_name": "Ada", "…": "…" }
  }
}
  • id: die Ereignis-ID. Eine wiederholte Zustellung trägt dieselbe ID, damit sich Duplikate erkennen lassen.
  • event: der Ereignisname, wie in der Tabelle oben.
  • data: was passiert ist. Die Felder hängen vom Ereignis ab; ein Nachrichtenereignis enthält die Nachricht und ihre Unterhaltung.

Header

  • X-TapToChat-Signature: die Signatur: v1= gefolgt von einem hexadezimalen HMAC-SHA256.
  • X-TapToChat-Timestamp: der Zeitpunkt der Signatur, in Unix-Sekunden.
  • X-TapToChat-Event: der Ereignisname.
  • X-TapToChat-Delivery-Id: diese Zustellung. Jede Wiederholung trägt dieselbe ID.

Die Signatur prüfen

Ein HMAC-SHA256 aus Zeitstempel, einem Punkt und dem unveränderten Anfrage-Body berechnen, mit dem Signatur-Secret als Schlüssel, und in konstanter Zeit mit dem Signatur-Header vergleichen. Anfragen, deren Zeitstempel mehr als 5 Minuten von der eigenen Uhr abweicht, ablehnen, damit eine abgefangene Anfrage nicht erneut abgespielt werden kann.

Das ganze Secret einschließlich des Präfixes whsec_ als Schlüssel verwenden. Den unveränderten Body vor dem Parsen prüfen: neu serialisiertes JSON stimmt nicht überein.

import crypto from 'node:crypto'

// The raw request body, exactly as received: verify before parsing JSON.
export function verifyTapToChat(rawBody, headers, secret) {
  const timestamp = headers['x-taptochat-timestamp']
  const signature = headers['x-taptochat-signature']
  if (!timestamp || !signature) return false

  // Refuse old requests, so a captured one cannot be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false

  const expected =
    'v1=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const a = Buffer.from(signature)
  const b = Buffer.from(expected)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

Wiederholungen

Eine Zustellung gilt als bestätigt, wenn innerhalb von 10 Sekunden ein 2xx-Status zurückkommt. Andernfalls wird sie wiederholt, mit bis zu 6 Versuchen insgesamt.

Die Wartezeiten zwischen den Versuchen betragen 30s, 60s, 120s, 240s, 480s.

Eine 4xx-Antwort außer 408 oder 429 beendet die Wiederholungen sofort, ebenso eine Weiterleitung: Weiterleitungen werden nicht verfolgt, daher die endgültige URL angeben.

Gelegentlich kann eine Zustellung mehrfach ankommen. Mit der ID im Body lässt sich jedes Ereignis genau einmal verarbeiten.

Automatische Abschaltung

Nach 20 fehlgeschlagenen Zustellungen in Folge wird der Webhook abgeschaltet, und die Einstellungen zeigen den Grund. Nach der Reparatur des Empfängers lässt er sich wieder einschalten; der Zähler beginnt dann neu.

Gut zu wissen

  • Die URL muss https verwenden und auf eine öffentliche Adresse zeigen.
  • Nachrichten, die Agenten aus der mobilen TapToChat-App senden, lösen message.created noch nicht aus. Nachrichten aus dem Web-Dashboard und aus allen Kanälen schon.

Funktioniert etwas nicht wie beschrieben? Kontakt aufnehmen.