Zurück zum Blog

    Webhook Beispiel: Sichere Endpunkte Schritt für Schritt

    Webhook beispiel - Lernen Sie anhand eines Webhook-Beispiels, wie Sie sichere Endpunkte erstellen. Schritt-für-Schritt-Anleitung für Entwickler

    webhook beispiel10 Min. Lesezeit
    Webhook Beispiel: Sichere Endpunkte Schritt für Schritt

    Ihr CRM zeigt einen neuen Lead, der Kalender bleibt leer, und im Team beginnt die manuelle Suche nach dem nächsten freien Termin. Vielleicht läuft bereits ein Skript, das regelmäßig nach Änderungen fragt. Es funktioniert, verbraucht aber unnötige Ressourcen und reagiert nur so schnell wie das Abfrageintervall.

    Ein Webhook löst dieses Problem ereignisgesteuert. Sobald in einem System etwas passiert, sendet es eine HTTP-Nachricht an Ihren Endpunkt. Das klingt zunächst simpel. Produktionsreif wird ein Webhook erst durch Rohkörperprüfung, Signaturen, Idempotenz, asynchrone Verarbeitung, Monitoring und eine DSGVO-taugliche Datenstrategie.

    Was ein Webhook eigentlich ist und wann Sie einen brauchen

    Ein Webhook ist eine automatische Benachrichtigung von einer Anwendung an ein anderes System. Ein Ereignis tritt ein, die sendende Anwendung erstellt eine Payload und schickt sie meist per HTTP-POST an eine zuvor hinterlegte URL. Die empfangende Anwendung nimmt die Nachricht entgegen und startet daraufhin einen Prozess.

    Eine Infografik erklärt die Funktionsweise von Webhooks als automatische Benachrichtigung ohne notwendiges manuelles Abfragen von Daten.

    Der Unterschied zu einer API liegt vor allem in der Richtung der Kommunikation:

    • API-Aufruf: Ihr System fragt aktiv nach Daten. Das ist sinnvoll, wenn Sie einen bestimmten Datensatz laden oder eine Aktion gezielt auslösen möchten.
    • Webhook: Das Quellsystem meldet ein Ereignis automatisch. Ihr System muss nicht fortlaufend prüfen, ob sich etwas geändert hat.
    • Kombination: In stabilen Integrationen arbeiten beide Verfahren zusammen. Der Webhook meldet beispielsweise eine neue Kontakt-ID, Ihre Anwendung lädt die vollständigen Details anschließend über die API.

    Ein typischer KMU-Workflow beginnt mit einem Formular. Ein neuer Lead wird angelegt, der Webhook übergibt die Kontakt-ID, und Ihr Automatisierungsdienst erstellt einen CRM-Datensatz oder startet eine Benachrichtigung. Bei einer Kalenderintegration kann ein gebuchter Termin den Status im CRM aktualisieren. Eine Voice-AI kann nach einem qualifizierten Gespräch eine Analyse an Ihre Anwendung senden, damit Vertrieb oder Kundenservice ohne manuelle Übertragung weiterarbeiten.

    Auch öffentliche Stellen bauen ihre Schnittstelleninfrastruktur aus. Das Statistische Bundesamt beschreibt den GENESIS-Webservice als RESTful- und JSON-Schnittstelle, die Daten aus GENESIS-Online in automatisierte Prozesse einbindet. Der Zugang ist kostenfrei und ohne Registrierung möglich, und das Angebot wird seit mindestens 2021 als Open-Data- und API-Zugang dokumentiert. Webhooks ersetzen solche APIs nicht, sie ergänzen sie um automatische Ereignismeldungen. (Statistisches Bundesamt zum GENESIS-Webservice)

    Praktische Regel: Verwenden Sie einen Webhook, wenn eine Statusänderung sofort einen Prozess auslösen soll. Verwenden Sie eine API, wenn Ihr System Daten gezielt lesen oder nach einem Ereignis nachladen muss.

    Webhook Endpoint einrichten Schritt für Schritt

    Beginnen Sie mit einer klaren URL, etwa ` Die Route sollte nur für Webhook-POSTs zuständig sein. Nutzen Sie TLS über Ihren Reverse-Proxy, damit der Transport verschlüsselt ist, und halten Sie die eigentliche Anwendung hinter diesem Proxy.

    Ein Express-Endpunkt muss den unveränderten Rohkörper lesen können. Die Signaturprüfung kommt vor dem JSON-Parsing, weil schon kleine Änderungen an Whitespace oder Zeichencodierung die spätere HMAC-Prüfung ungültig machen können.

    import express from "express";
    
    const app = express();
    
    app.post(
      "/webhooks/crm",
      express.raw({ type: "application/json" }),
      (req, res) => {
        const rawBody = req.body;
    
        // Signatur prüfen, Event-ID lesen und Event in die Queue legen.
        res.status(204).end();
      }
    );
    
    app.listen(3000);
    

    Mit FastAPI sieht der Empfang ähnlich aus:

    from fastapi import FastAPI, Request, Response
    
    app = FastAPI()
    
    @app.post("/webhooks/crm")
    async def receive_webhook(request: Request):
        raw_body = await request.body()
        # Signatur prüfen und Event zur Verarbeitung vormerken
        return Response(status_code=204)
    

    Die 204-Antwort bestätigt nur den Eingang. Sie sollte nicht erst nach CRM-Aufrufen, Datenbankabfragen oder einer langen Geschäftslogik kommen. Ein deutschsprachiger Leitfaden zur Handler-Architektur empfiehlt genau diese Trennung, Prüfung zuerst, schnelle 2xx-Antwort danach und Verarbeitung aus einer Queue. Bei GitHub Enterprise Server werden Webhook-Requests in der Regel innerhalb von 30 Sekunden mit einer 2XX-Antwort erwartet. (Leitfaden zur Webhook-Handler-Architektur)

    Für lokale Entwicklung reicht Ihr Laptop normalerweise nicht als öffentlich erreichbarer Empfänger. Ein Tunnel mit ngrok stellt eine temporäre HTTPS-Adresse bereit, die Sie beim Anbieter hinterlegen können. Senden Sie danach einen Test-POST und prüfen Sie zuerst Statuscode, Header und Rohkörper.

    Wenn die Begriffe API, Route und Webhook noch nicht sauber auseinanderliegen, hilft ein praxisnaher API-Überblick. Für die konkrete Anbindung sollten Sie zusätzlich die API-Dokumentation von malma.ai prüfen, insbesondere wenn Analysen nach einem Gespräch an einen eigenen HTTPS-Endpunkt weitergeleitet werden.

    Eine menschliche Hand platziert ein orangefarbenes POST-Schild auf einem Server-Rack mit der Aufschrift API-Endpunkt.

    Beispiel Payloads aus der Praxis verstehen

    Eine Payload ist kein Vertrag, dem Sie blind vertrauen sollten. Anbieter verändern Feldnamen, verschachteln Objekte unterschiedlich und senden je nach Ereignistyp verschiedene Daten. In der Praxis interessieren zuerst Event-Typ, eindeutige ID, Zeitstempel, betroffene Ressource und die für den nächsten Prozess nötigen Kontaktdaten.

    Ein HubSpot-ähnliches Contact-Created-Event könnte so aussehen:

    {
      "eventType": "contact.created",
      "eventId": "evt_123",
      "occurredAt": "2026-08-15T10:30:00Z",
      "contact": {
        "id": "contact_456",
        "email": "kunde@example.de",
        "firstName": "Anna",
        "lastName": "Muster"
      },
      "source": "website"
    }
    

    Die eventId dient der Dublettenprüfung. contact.id ist die stabile Referenz für spätere API-Aufrufe. E-Mail und Name können für die Zuordnung hilfreich sein, sollten aber nur verarbeitet und gespeichert werden, wenn der Zweck das rechtfertigt.

    Ein Calendly-Invitee-Event legt meist den Terminbezug in ein eigenes Objekt:

    {
      "event": "invitee.created",
      "id": "cal_789",
      "createdAt": "2026-08-15T11:00:00Z",
      "invitee": {
        "email": "kunde@example.de",
        "name": "Anna Muster",
        "uri": "https://api.calendly.com/scheduled_events/event_123"
      },
      "tracking": {
        "source": "landing-page"
      }
    }
    

    Hier ist die Termin- oder Ressourcen-URL wichtiger als eine komplette Kopie sämtlicher Metadaten. Laden Sie Details bei Bedarf über die Anbieter-API nach, statt jede Payload dauerhaft mit personenbezogenen Daten anzureichern.

    Ein Voice-AI-Trigger nach einem qualifizierten Lead könnte beispielsweise diese Struktur haben:

    {
      "eventType": "call.analysis.completed",
      "eventId": "call_evt_321",
      "occurredAt": "2026-08-15T12:15:00Z",
      "call": {
        "id": "call_654",
        "qualification": "qualified",
        "summary": "Interesse an Beratung",
        "appointment": {
          "start": "2026-08-18T09:00:00Z",
          "timezone": "Europe/Berlin"
        }
      },
      "contact": {
        "phone": "+49...",
        "email": "kunde@example.de"
      }
    }
    

    Die Telefonnummer sollten Sie nicht ungekürzt in Debug-Logs schreiben. Für die Weiterverarbeitung genügt häufig eine interne Gesprächs-ID, der Qualifizierungsstatus und die Terminreferenz.

    Feld HubSpot Contact Calendly Invitee malma.ai Lead
    Ereignistyp contact.created invitee.created call.analysis.completed
    Eindeutige ID eventId, contact.id id, Ressourcen-URI eventId, call.id
    Zeitbezug occurredAt createdAt, Termin-URI occurredAt, Terminstart
    Kontaktdaten Name, E-Mail Name, E-Mail Telefon, E-Mail
    Fachlicher Status Kontakt erstellt Termin gebucht Lead qualifiziert
    Selektiv speichern Tracking-Metadaten Kampagnenparameter Gesprächszusammenfassung

    Zum schnellen Inspektieren reicht im Terminal beispielsweise jq:

    cat payload.json | jq '{eventType, eventId, occurredAt, contact}'
    

    Das Ziel ist nicht, jedes Feld zu unterstützen. Definieren Sie ein internes Normalformat und mappen Sie nur die Felder, die Ihr Prozess tatsächlich verwendet.

    Webhook Signatur mit HMAC SHA-256 prüfen

    Eine zufällige Webhook-URL ist kein ausreichender Schutz. Ein Angreifer könnte die URL erraten, aus Logs erhalten oder aus einer Konfiguration kopieren. Mit HMAC SHA-256 teilen Sender und Empfänger ein Secret. Der Sender signiert den Rohkörper, der Empfänger berechnet die Signatur erneut und vergleicht beide Werte bytegenau.

    Ein Vorhängeschloss mit einem Schlüssel, auf dem HMAC SIGNATURE steht, vor einem Hintergrund mit zerrissenem Papier.

    In Node.js darf das Secret nicht im Quelltext liegen:

    import crypto from "node:crypto";
    
    function verifySignature(rawBody, receivedSignature) {
      const secret = process.env.WEBHOOK_SECRET;
      const expected = crypto
        .createHmac("sha256", secret)
        .update(rawBody)
        .digest("hex");
    
      const received = Buffer.from(receivedSignature, "utf8");
      const calculated = Buffer.from(expected, "utf8");
    
      return received.length === calculated.length &&
        crypto.timingSafeEqual(received, calculated);
    }
    

    Python verwendet dafür hmac.compare_digest:

    import os
    import hmac
    import hashlib
    
    def verify_signature(raw_body: bytes, received_signature: str) -> bool:
        expected = hmac.new(
            os.environ["WEBHOOK_SECRET"].encode(),
            raw_body,
            hashlib.sha256
        ).hexdigest()
    
        return hmac.compare_digest(expected, received_signature)
    

    In PHP erledigt hash_hmac die Berechnung:

    <?php
    function verifySignature(string $rawBody, string $received): bool {
        $secret = getenv('WEBHOOK_SECRET');
        $expected = hash_hmac('sha256', $rawBody, $secret);
        return hash_equals($expected, $received);
    }
    

    Viele Anbieter senden zusätzlich einen Zeitstempel, etwa als Header. Signieren Sie dann nicht nur den Body, sondern die vom Anbieter dokumentierte Kombination aus Zeitstempel und Body. Lehnen Sie Nachrichten außerhalb Ihres akzeptierten Zeitfensters ab. Dieser Replay-Schutz verhindert, dass jemand eine gültige alte Nachricht unverändert erneut einspielt.

    Sicherheitsregel: Erst Rohkörper lesen, dann Zeitstempel und HMAC prüfen, danach JSON parsen. Ein JSON-Middleware-Parser an der falschen Stelle kann die Signaturprüfung unbrauchbar machen.

    Das Secret gehört in eine Umgebungsvariable oder einen Secret-Manager, nicht in ein Repository, Ticket oder Logfile. Dokumentieren Sie Rotation, Fehlercodes und den Umgang mit ungültigen Signaturen. Eine ergänzende Anleitung zur Sicherheitsprüfung ist hilfreich, wenn Sie Webhook-Daten aus einer Voice- oder CRM-Integration übernehmen.

    Idempotenz und asynchrone Verarbeitung richtig aufsetzen

    Ein Sender kann dasselbe Ereignis erneut zustellen. Das ist kein Ausnahmefall, sondern eine Eigenschaft, auf die Ihr Empfänger vorbereitet sein muss. Ohne Idempotenz legt ein einzelner Lead womöglich mehrere CRM-Kontakte an, verschickt mehrere Benachrichtigungen oder bucht eine Aktion mehrfach.

    Speichern Sie deshalb die Event-ID vor der fachlichen Verarbeitung. Der entscheidende Datenbankzugriff muss atomar sein:

    INSERT INTO received_events (event_id, received_at, status)
    VALUES (:event_id, CURRENT_TIMESTAMP, 'queued')
    ON CONFLICT (event_id) DO NOTHING;
    

    Wenn kein Datensatz eingefügt wurde, existiert die ID bereits. Verwerfen Sie die Nachricht als Duplikat und antworten Sie trotzdem erfolgreich, sofern die Signatur gültig war. So verhindert die Datenbank doppelte Verarbeitung, nicht ein unsicherer Check im Anwendungscode.

    Ein Flussdiagramm erklärt den Prozess der Idempotenz und asynchronen Verarbeitung von Webhook-Ereignissen zur Vermeidung von Duplikaten.

    Der Request-Thread sollte nur die Eingangskontrolle erledigen:

    1. Rohkörper entgegennehmen.
    2. Signatur und Zeitstempel prüfen.
    3. Event-ID validieren und speichern.
    4. Payload oder eine interne Referenz in die Queue schreiben.
    5. Sofort mit 204 No Content antworten.

    Ein Worker übernimmt anschließend CRM-Updates, API-Aufrufe und Benachrichtigungen. Schlägt die Verarbeitung fehl, versucht der Worker die Nachricht erneut. Bleiben Wiederholungen erfolglos, verschiebt er das Event in eine Dead-Letter-Queue, damit es nicht unbemerkt verschwindet.

    Für den Betrieb sind konkrete Ziele sinnvoll. Best-Practice-Quellen nennen eine Delivery-Success-Rate von mehr als 99,5 %, die Überwachung der P95-Zustelllatenz, der Retry-Rate je Endpunkt und der DLQ-Tiefe. Alarmieren sollten Sie unter anderem bei weniger als 99 % erfolgreicher Zustellung, bei mehr als fünf aufeinanderfolgenden Fehlschlägen oder bei mehr als 100 unverarbeiteten Events in der Dead-Letter-Queue. (Webhook-Best-Practices für zuverlässige Integrationen)

    Test Tools und typische Fehler schnell beheben

    Ein Endpunkt, der nur mit einem Anbieter-Button funktioniert, ist noch nicht belastbar. Testen Sie zunächst isoliert, ob URL, Methode, Header und Rohkörper korrekt ankommen. webhook.site eignet sich für eine schnelle Sichtprüfung eingehender Requests, Request-Bin für wiederholbare Payload-Tests und ngrok für die Verbindung zwischen einem externen Sender und Ihrer lokalen Anwendung.

    Senden Sie zuerst eine kontrollierte Test-Payload. Speichern Sie den vollständigen Request für einen Replay, ändern Sie danach gezielt ein Feld und prüfen Sie, ob Ihre Validierung erwartungsgemäß reagiert. Personenbezogene Daten gehören dabei nicht in öffentliche Testdienste, wenn Sie nicht sicher beurteilen können, wie diese Daten verarbeitet und gespeichert werden.

    Eine Übersichtstabelle mit nützlichen Test-Tools und Lösungen für typische Fehler bei der Webhook-Integration und Fehlersuche.

    Symptom Wahrscheinliche Ursache Ein-Zeilen-Lösung
    401 Unauthorized Secret oder Signaturformat stimmt nicht Secret, Headername und signierten String vergleichen
    500 Internal Server Error Geschäftslogik läuft im Request-Thread Nur validieren und enqueuen, Verarbeitung auslagern
    Doppelte Einträge Event-ID wird nicht gespeichert Unique Constraint und atomaren Insert ergänzen
    404 Not Found Route oder Methode stimmt nicht Registrierte POST-Route mit Anbieter-Konfiguration abgleichen
    Payload leer oder beschädigt Proxy oder Middleware verändert den Body Rohkörper am Proxy und in der Anwendung protokollieren

    Achten Sie bei der Fehlersuche auf die Reihenfolge. Kommt der Request am Reverse-Proxy an? Wird er an den richtigen Upstream weitergeleitet? Enthält der Anwendungseingang noch exakt dieselben Bytes? Danach prüfen Sie Signatur, Event-ID, Queue-Status und Worker-Logs.

    Ein erfolgreicher HTTP-Status beweist nur, dass Ihr Endpunkt geantwortet hat. Er beweist nicht, dass die fachliche Verarbeitung abgeschlossen ist.

    Webhook Integration mit CRM und Kalender produktiv betreiben

    In einer realen Kette meldet ein Formular den neuen Lead, das CRM führt den Kontakt, der Kalender liefert den Terminstatus und ein Telefonie-System ergänzt Gesprächsergebnis und Qualifizierung. Jede Verbindung braucht ein klares Mapping. Legen Sie fest, welches System für E-Mail, Besitzer, Termin und Status führend ist, sonst überschreibt ein später eintreffendes Event gültige Daten.

    Bei HubSpot können Sie beispielsweise die Kontakt-ID als externe Referenz führen und Deal-Status nur aus eindeutig definierten Ereignissen aktualisieren. Bei Calendly prüfen Sie die Terminreferenz, Zeitzone und den aktuellen Buchungsstatus. Eine Voice-AI wie malma.ai kann nach einem analysierten Gespräch Daten an eine definierte HTTPS-URL weiterleiten. Für CRM-Grundlagen und Datenmodelle hilft die Übersicht zu Customer-Relationship-Management.

    Vor dem Go-Live sollte Ihre Checkliste mindestens diese Punkte enthalten:

    • Datensparsamkeit: Übertragen Sie nur Felder, die der konkrete Zweck benötigt.
    • Rechtsgrundlage: Klären Sie Verarbeitung, Auftragsverarbeitung, Löschfristen und Zugriffsrechte nach DSGVO.
    • Hosting: Prüfen Sie, wo Anwendung, Logs, Queue und Monitoring betrieben werden. EU-Hosting kann die organisatorische Bewertung vereinfachen, ersetzt aber keine Datenschutzprüfung.
    • Sicherheit: Erzwingen Sie HTTPS, prüfen Sie HMAC und Zeitstempel und legen Sie Secrets außerhalb des Repositories ab.
    • Betrieb: Überwachen Sie Zustellrate, Latenz, Wiederholungen und Dead-Letter-Queue.
    • Wiederanlauf: Testen Sie Replay, Duplikate, ungültige Signaturen und einen ausgefallenen Worker.

    So wird aus einem einfachen POST-Aufruf eine kontrollierbare Integrationsstrecke. Die Technik ist nicht kompliziert, wenn Sie Eingang, Validierung und Verarbeitung konsequent voneinander trennen.


    malma.ai kann qualifizierte Gespräche analysieren und die Ergebnisse per Webhook-Forwarding an Ihre HTTPS-Endpunkte senden, damit CRM-, Kalender- und Follow-up-Prozesse automatisch weiterlaufen. Prüfen Sie die Integrationsmöglichkeiten auf malma.ai und testen Sie den Ablauf zunächst mit einer datensparsamen Payload und einer isolierten Queue.

    Jetzt unverbindliche Demo buchen.

    Trag dich ein und erlebe die Demo direkt am eigenen Telefon. Danach planen wir gemeinsam deinen KI-Vertrieb.

    Das Team, das deine Agenten baut

    So läuft's ab:

    • Unser Agent ruft dich direkt an, so wie er später mit deinen Leads spricht
    • Im Demo Call rechnen wir mit deinen Zahlen, nicht mit unseren
    • Du bekommst eine ehrliche Antwort, ob es sich für dich lohnt
    Google PartnerMade in GermanyDSGVO-konformFrankfurt & Nürnberg

    Nach dem Absenden ruft dich unser KI-Agent unter deiner Nummer an. Er gibt sich als KI zu erkennen, der Anruf ist kostenlos und deine Daten bleiben auf deutschen Servern.