Webhooks
Registrieren Sie einen öffentlichen Endpunkt, überprüfen Sie signierte Rohdaten, entdoppeln Sie Ereignisse und steuern Sie Wiederholungsversuche sicher.
Registrieren Sie einen öffentlichen Endpunkt, überprüfen Sie signierte Rohdaten, entdoppeln Sie Ereignisse und steuern Sie Wiederholungsversuche sicher.
Developer-Webhooks senden Ereignisse Ihres Kontos an Ihren Server, sodass Sie keine Abfragen (Polling) durchführen müssen. Die Zustellung erfolgt mindestens einmal: Ereignisse können doppelt, verzögert oder in falscher Reihenfolge eintreffen.
Endpunkt registrieren#
Erstellen Sie einen Schlüssel mit webhooks:write und registrieren Sie anschließend einen öffentlichen HTTPS-Empfänger sowie die kleinstmögliche Menge an Ereignissen, die Sie benötigen.
curl --fail-with-body https://makeagent.fast/api/v1/webhook-endpoints \
-X POST \
-H "Authorization: Bearer $MAF_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: webhook-production-v1" \
-d '{
"url": "https://api.example.com/webhooks/make-agent-fast",
"events": ["lead.created", "conversation.started"]
}'Die URL muss HTTPS verwenden, darf keinen Benutzernamen, kein Passwort, kein Fragment und keinen benutzerdefinierten Port enthalten und muss ausschließlich zu öffentlichen IP-Adressen aufgelöst werden. Weiterleitungen werden bei der Zustellung nicht verfolgt.
Die 201-Antwort zeigt ein Signing Secret im Format whsec_... nur einmal an. Speichern Sie es im Secret Manager des Empfängers, bevor Sie die Antwort schließen. Wenn Sie Endpunkte später auflisten, werden URL, Ereignisse, Status, letzte Zustellung und letzter Fehler zurückgegeben – jedoch nicht das Secret.
Ereignistypen#
| Ereignis | Wird ausgelöst, wenn |
|---|---|
site.published | Eine Website veröffentlicht wird |
site.unpublished | Eine Website in den Entwurfsstatus zurückversetzt wird |
lead.created | Der Agent einen neuen Lead erfasst |
lead.qualified | Der Agent einen Lead qualifiziert oder ein Lead in die Vertriebspipeline aufgenommen wird |
booking.requested | Ein Besucher einen Termin anfragt oder bucht |
handoff.requested | Der Agent eine Konversation an eine Person übergibt (Handoff) |
opportunity.created | Ein Lead zu einer Opportunity in der Pipeline wird |
opportunity.updated | Sich Zuweisung, Wert, nächste Aktion oder andere Felder einer Opportunity ändern |
opportunity.stage_changed | Eine Opportunity in eine andere Phase wechselt |
opportunity.won | Eine Opportunity als gewonnen abgeschlossen wird |
opportunity.lost | Eine Opportunity als verloren abgeschlossen wird |
conversation.started | Ein neuer Konversationsverlauf beginnt |
conversation.message.created | Einer Konversation eine Nachricht hinzugefügt wird |
knowledge.ready | Eine Wissensquelle die Verarbeitung abgeschlossen hat |
broadcast.sent | Ein Broadcast seinen Versandablauf abgeschlossen hat |
domain.activated | Eingestellt – benutzerdefinierte Domains werden nicht angeboten; dieses Ereignis wird nie ausgelöst |
Anfrageformat#
Make Agent Fast sendet POST mit Content-Type: application/json, User-Agent: MakeAgentFast-Webhooks/1.0 und diesen Headern:
maf-event-id: evt_...
maf-event-type: lead.created
maf-signature: t=1784210566,v1=HEX_HMAC_SHA256Der JSON-Body hat eine stabile Hülle (Envelope). Die Felder innerhalb von data hängen vom Ereignis ab und können um zusätzliche Felder erweitert werden.
{
"id": "evt_2c34...",
"type": "lead.created",
"created_at": "2026-07-16T10:02:46.000Z",
"data": {
"site_id": "SITE_ID",
"lead_id": "LEAD_ID"
}
}Verwenden Sie die id aus dem Body oder maf-event-id als Schlüssel zur Deduplizierung. Verwenden Sie weder den Zustellzeitpunkt noch eine generierte Datenbank-ID.
Signatur in Node.js überprüfen#
Lesen Sie die exakten Rohbytes, bevor Sie das JSON parsen. Der signierte Wert ist TIMESTAMP + "." + RAW_BODY.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyWebhook(rawBody: Buffer, header: string, secret: string) {
const values = Object.fromEntries(header.split(",").map((part) => part.split("=", 2)));
const timestamp = values.t;
const supplied = values.v1;
if (!timestamp || !supplied || !/^[a-f0-9]{64}$/.test(supplied)) return false;
const age = Math.abs(Date.now() / 1_000 - Number(timestamp));
if (!Number.isFinite(age) || age > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${timestamp}.`)
.update(rawBody)
.digest("hex");
return timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(supplied, "hex"));
}Weisen Sie fehlerhafte Signaturen sowie Zeitstempel zurück, die älter sind als Ihr akzeptiertes Replay-Fenster; fünf Minuten sind ein sinnvoller Standardwert. Vergleichen Sie Bytes fester Länge in konstanter Zeit.
Signatur in Python überprüfen#
import hashlib
import hmac
import time
def verify_webhook(raw_body: bytes, header: str, secret: str) -> bool:
values = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
timestamp = values.get("t", "")
supplied = values.get("v1", "")
try:
if abs(time.time() - int(timestamp)) > 300:
return False
except ValueError:
return False
signed = timestamp.encode() + b"." + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, supplied)Parsen und verarbeiten Sie das JSON erst, nachdem die Signaturprüfung erfolgreich war.
Bestätigen und verarbeiten#
- Überprüfen Sie Signatur und Zeitstempel.
- Fügen Sie die Ereignis-ID in eine Tabelle mit einer Unique-Constraint ein.
- Existiert sie bereits, geben Sie
204zurück, ohne den Seiteneffekt zu wiederholen. - Committen Sie das Ereignis oder stellen Sie Ihren internen Job in die Warteschlange.
- Geben Sie zügig eine
2xx-Antwort zurück.
Der Sender von Make Agent Fast bricht nach 10 Sekunden mit einem Timeout ab. Nur 2xx gilt als erfolgreich, und Weiterleitungen werden nicht verfolgt.
Wiederholungsverhalten#
Fehlgeschlagene Zustellungen werden für bis zu acht Versuche in die Warteschlange gestellt. Das Backoff beginnt bei etwa zwei Sekunden, verdoppelt sich mit Jitter und ist auf eine Stunde begrenzt; der tatsächliche Zustellzeitpunkt kann später liegen, wenn die Worker ausgelastet sind. Da Wiederholungen die auslösende Anfrage überdauern und in falscher Reihenfolge eintreffen können, sollten Sie sich nie darauf verlassen, dass ein Ereignis unmittelbar vor einem anderen eintrifft.
Geben Sie nur dann eine Nicht-2xx-Antwort zurück, wenn Make Agent Fast die Zustellung wiederholen soll. Bei einer dauerhaft nicht unterstützten Ereignisversion oder einem gelöschten Ziel sollten Sie das Ereignis akzeptieren und protokollieren oder den Endpunkt entfernen, anstatt endlose temporäre Fehler zu erzeugen.
Signing Secret rotieren#
Signing Secrets können weder erneut angezeigt noch bearbeitet werden. So rotieren Sie sicher:
- Erstellen Sie einen zweiten Endpunkt, der auf einen temporären oder versionierten Empfängerpfad verweist.
- Speichern Sie das dabei neu angezeigte Secret.
- Akzeptieren und deduplizieren Sie Ereignisse von beiden Endpunkten.
- Prüfen Sie, ob der neue Endpunkt gültige Zustellungen erhält.
- Löschen Sie den alten Endpunkt mit
DELETE /webhook-endpoints/{endpoint_id}.
Bleibt die Empfänger-URL gleich, sorgen Sie dafür, dass die empfangende Anwendung während der Überlappung beide Secrets akzeptiert, und verwenden Sie Ereignis-IDs, um doppelte Seiteneffekte zu vermeiden.
Fehlerbehebung#
| Symptom | Prüfen |
|---|---|
| Keine Zustellungen | Endpunktstatus, ausgewählte Ereignisse, öffentliches DNS, HTTPS-Zertifikat und ob das Ereignis tatsächlich eingetreten ist |
| Signatur stimmt nicht überein | Zugriff auf den Rohbody, exakte Verkettung timestamp.body, korrektes Secret des Endpunkts und Body-Veränderungen durch Proxys |
| Wiederholte Zustellungen | Rückgabecode, 10-Sekunden-Timeout, interne Ausnahmen und Eindeutigkeit der Ereignis-ID |
| Fehler bei privaten Adressen | DNS-Einträge dürfen ausschließlich zu öffentlichen Adressen aufgelöst werden; localhost und interne Bereiche werden abgelehnt |
| Fehler bei Weiterleitung | Registrieren Sie direkt die finale HTTPS-URL; Weiterleitungen werden nicht verfolgt |
Fügen Sie einer Support-Nachricht niemals das Signing Secret, den Bearer-Schlüssel oder die vollständigen Besucherdaten bei. Geben Sie stattdessen die Endpunkt-ID, die Ereignis-ID, den Zeitpunkt des Fehlers und bereinigte Empfänger-Logs an.