• Customermates Logo
    CustomermatesDocumentation
  • Einführung
  • Vergleich
Erste Schritte
  • Quickstart
  • Kernkonzepte
  • Von Pipedrive
KI verbinden
  • Claude Code verbinden
  • Claude Desktop verbinden
  • Codex verbinden
  • Cursor verbinden
  • Gemini verbinden
  • ChatGPT verbinden
Integrationen
  • MCP
  • Webhooks
  • OpenAPI 3.1.0
  • N8N
Self-Hosting
  • Get Started
  • Architektur & Sicherheit
Reference
  • MCP-Tool-Katalog
  • Filter-Syntax
  • API-Keys
  • Zurück
  1. Einführung
  2. Webhooks

Webhooks

CRM-Events abonnieren, Signaturen verifizieren, fehlgeschlagene Deliveries debuggen, und der volle Event-Katalog auf einer Seite.

Events wählen, HTTPS-URL geben, wir POST-en JSON dorthin bei jeder Änderung. Fehlgeschlagene Deliveries aus der UI oder per MCP erneut zustellen. Signaturen per HMAC-SHA256 über den Raw-Body prüfen. Jedes Event mit Payload-Shape steht unten auf dieser Seite.

Warum Webhooks

Webhooks machen dein CRM zur Source-of-Truth, auf die dein restlicher Stack lauscht. Kein Polling, keine stale Daten.

Typische Einsätze:

  • Neue Contacts in deinen E-Mail-Sequencer.
  • Ticket im Support-Tool öffnen, wenn ein Deal verloren geht.
  • Finance-Workflow auslösen, wenn ein Deal gewonnen wird.
  • Near-realtime-Sync ins Data Warehouse.

Webhook anlegen

UI: Unternehmen → Webhooks → Neu.

MCP: create_webhook mit url, events[], optional description, secret, enabled.

{
  "url": "https://hooks.example.com/customermates",
  "events": ["contact.created", "contact.updated", "deal.updated"],
  "secret": "nutze-einen-random-string-aus-einem-password-manager",
  "enabled": true
}

Die URL muss HTTPS sein. HTTP wird abgelehnt.

Was du bekommst

Jede Delivery ist ein POST mit Content-Type: application/json. Jede Delivery folgt demselben Envelope:

{
  "event": "<event-name>",
  "data": {
    "userId": "<verursacher>",
    "companyId": "<tenant>",
    "entityId": "<betroffener-record>",
    "payload": { /* event-spezifisch */ }
  },
  "timestamp": "<iso-8601>"
}

Die userId ist der User, der den Write verursacht hat, inkl. User, die über einen API-Key handeln.

Der changes-Record existiert nur bei *.updated-Events. Er listet jedes Feld, das sich wirklich geändert hat, mit vorherigem und aktuellem Wert.

Beispiel, contact.updated:

{
  "event": "contact.updated",
  "data": {
    "userId": "u_123",
    "companyId": "c_abc",
    "entityId": "ct_xyz",
    "payload": {
      "contact": {
        "id": "ct_xyz",
        "firstName": "Max",
        "lastName": "Mustermann",
        "notes": { /* Tiptap JSON */ },
        "organizationIds": ["org_1"],
        "userIds": [],
        "dealIds": ["deal_1", "deal_2"],
        "customFieldValues": [
          { "columnId": "col_stage", "value": "won" }
        ]
      },
      "changes": {
        "organizationIds": {
          "previous": [],
          "current": ["org_1"]
        }
      }
    }
  },
  "timestamp": "2026-04-22T10:00:00.000Z"
}

Der changes-Record

Jeder Key in changes ist ein Feldname, dessen Wert sich bewegt hat. previous ist der vorherige, current der aktuelle.

Relationship-ID-Arrays vergleichen sich als Sets. Objekte als Deep-Equal. Skalare per Wert.

Wenn ein Write tatsächlich nichts ändert, wird das Event unterdrückt. Du bekommst keine No-op-*.updated-Events.

Signatur-Verifikation

Wenn du ein secret setzt, enthält jede ausgehende Request:

X-Webhook-Signature: <hex>

Wo <hex> = HMAC-SHA256(secret, rawRequestBody), Lowercase-Hex, kein Präfix. Auf deiner Seite neu berechnen und constant-time vergleichen.

Node.js:

import crypto from "crypto";

function verify(rawBody: string, received: string, secret: string) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}

Retries und fehlgeschlagene Deliveries

Jede Delivery wird geloggt. Sichtbar in der UI (Unternehmen → Webhook-Deliveries) oder via list_webhook_deliveries.

Eine Delivery ist failed, wenn der HTTP-Status nicht im 2xx-Bereich liegt oder die Request timeoutet.

Failed Delivery neu zustellen via UI oder resend_webhook_delivery mit der Delivery-ID. Ein neuer Delivery-Record entsteht; das Original bleibt unverändert.

Customermates retryt fehlgeschlagene Deliveries nicht automatisch. Wenn dein Receiver down war, Retries aus der UI anstoßen oder list_webhook_deliveries in ein Monitoring-Skript piepen.

Ordering und Concurrency

Deliveries sind nicht strikt geordnet. Zwei contact.updated-Events im Millisekundenabstand können out-of-order ankommen. Per Timestamp auflösen, oder Deliveries als idempotente Messages behandeln, geschlüsselt per entityId.

Notes sind JSON, nicht Markdown

Das notes-Feld in Payloads ist Tiptap-JSON, dieselbe Struktur, die der Editor speichert. Zum Rendern als Markdown auf deiner Seite einen Tiptap-Serializer einsetzen. In MCP-Tools liefert get_entities mit include: "withNotes" die Notes bereits als Markdown.

Delete-Payloads

Delete-Events enthalten nur die ID, nicht den Endzustand. Wenn du den Endzustand brauchst (fürs Archiv z.B.), auch *.updated abonnieren und einen lokalen Mirror halten.

Debug-Tipps

  • webhook.site als Einweg-Receiver beim Integrationstest.
  • list_webhook_deliveries unterstützt searchTerm auf URL und Event-Name.
  • Wenn dein Receiver 500 zurückgibt, wird der Response-Body geloggt, du siehst exakt, was kaputt war.

Event-Katalog

15 Events über die fünf Entity-Typen, alle mit dem Envelope oben.

EventWann es feuertPayload-Keys
contact.createdContact via UI/API/MCP/Import erstelltcontact
contact.updatedIrgendein Contact-Feld ändert sichcontact, changes
contact.deletedContact gelöschtcontactId
organization.createdOrganization erstelltorganization
organization.updatedIrgendein Organization-Feld ändert sichorganization, changes
organization.deletedOrganization gelöschtorganizationId
deal.createdDeal erstelltdeal
deal.updatedIrgendein Deal-Feld ändert sichdeal, changes
deal.deletedDeal gelöschtdealId
service.createdService erstelltservice
service.updatedIrgendein Service-Feld ändert sichservice, changes
service.deletedService gelöschtserviceId
task.createdTask erstellttask
task.updatedIrgendein Task-Feld ändert sichtask, changes
task.deletedTask gelöschttaskId

Weiter

  • MCP-Tool-Katalog: Webhooks programmatisch verwalten.
  • n8n: Webhooks in visuelle Workflows.
Warum Webhooks
Webhook anlegen
Was du bekommst
Der changes-Record
Signatur-Verifikation
Retries und fehlgeschlagene Deliveries
Ordering und Concurrency
Notes sind JSON, nicht Markdown
Delete-Payloads
Debug-Tipps
Event-Katalog
Weiter