Webhooks
Endpunkt einrichten
Webhook-Endpunkte legen Sie im Dashboard unter Einstellungen → Webhooks oder per API über POST /webhook-endpoints an (Scope webhooks:write). Sie geben eine https://-URL und die gewünschten Ereignisse an. Beim Anlegen erhalten Sie einmalig das Signatur-Secret des Endpunkts – bewahren Sie es wie ein Passwort auf.
curl -X POST 'https://www.debt-flow.io/api/v1/webhook-endpoints' \
-H "Authorization: Bearer $DEBTFLOW_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/webhooks/debtflow",
"events": [
"invoice.paid",
"debt.phase_changed"
]
}'Die genauen Felder stehen in der API-Referenz im Abschnitt Webhooks.
Aufbau einer Zustellung
POST /webhooks/debtflow HTTP/1.1
Content-Type: application/json
DebtFlow-Event-Id: evt_3kR9xY2mQ7pL0aB4cD1e
DebtFlow-Signature: t=1762248600,v1=5f2b0c…
{
"id": "evt_3kR9xY2mQ7pL0aB4cD1e",
"object": "event",
"type": "invoice.paid",
"apiVersion": "2026-11-01",
"createdAt": "2026-11-04T09:30:00.000Z",
"data": {
"object": { "id": "…", "status": "paid", "…": "…" }
}
}data.objectist die Ressource im selben Format, das die REST-API liefert. Bei*.updatedsteht indata.previous, welche Felder sich wie geändert haben.idbzw. der HeaderDebtFlow-Event-Idist je Ereignis eindeutig. Ein Ereignis kann mehrfach ankommen – speichern Sie verarbeitete IDs und überspringen Sie Wiederholungen.- Die Reihenfolge der Zustellung ist nicht garantiert. Maßgeblich ist
createdAt.
Signatur prüfen
Jede Zustellung ist mit dem Secret des Endpunkts signiert. Der Header DebtFlow-Signature enthält einen Zeitstempel t (Unix-Sekunden) und die Signatur v1:
DebtFlow-Signature: t=1762248600,v1=5f2b0c9e…- Zeichenkette bilden:
t, ein Punkt, dann der unveränderte Request-Body. - HMAC-SHA256 mit dem Secret berechnen und hexadezimal (Kleinbuchstaben) kodieren.
- Mit jedem
v1-Wert in konstanter Zeit vergleichen. - Zustellungen ablehnen, deren
tmehr als 5 Minuten von Ihrer Uhrzeit abweicht – das verhindert das Wiedereinspielen alter Anfragen.
# Signatur selbst erzeugen und den eigenen Endpunkt testen
BODY='{"id":"evt_test","object":"event","type":"webhook.test","apiVersion":"2026-11-01","createdAt":"2026-11-04T09:30:00.000Z","data":{"object":{}}}'
T=$(date +%s)
SIG=$(printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$DEBTFLOW_WEBHOOK_SECRET" -hex | sed 's/^.* //')
curl -X POST 'https://example.com/webhooks/debtflow' \
-H 'Content-Type: application/json' \
-H "DebtFlow-Signature: t=$T,v1=$SIG" \
-d "$BODY"Antworten und Wiederholungen
- Antworten Sie mit einem Status
2xx, sobald die Signatur stimmt, und verarbeiten Sie das Ereignis danach asynchron. Lange Verarbeitung im Request führt zu Zeitüberschreitungen und Wiederholungen. - Bei Fehlern oder ohne Antwort wiederholt DebtFlow die Zustellung mit wachsenden Abständen bis zu drei Tage lang.
- Schlägt die Zustellung an einen Endpunkt dauerhaft fehl, wird er deaktiviert. Sie sehen das in den Einstellungen und können ihn dort wieder aktivieren.
- Ein Endpunkt erhält nur Ereignisse, für die der anlegende API-Schlüssel bzw. die App den genannten Scope hat.
- Das Zustellprotokoll speichert höchstens 200 Zeichen Ihrer Antwort. Werte sensibler Header (Signatur, Authorization, Cookies, API-Schlüssel) und Tokens werden dabei entfernt; Antwort-Header werden nicht gespeichert.
Zeitgesteuerte Ereignisse
debt.overdue, installment.due und installment.missed entstehen im täglichen Lauf (morgens, Europe/Berlin) und werden je Vorfall genau einmal ausgelöst: debt.overdue einmal je Fälligkeitsdatum einer offenen Forderung, installment.due bis zu drei Tage vor Fälligkeit der nächsten offenen Rate, installment.missed nach verstrichener Fälligkeit. Ändert sich das Fälligkeitsdatum, ist das ein neuer Vorfall. Fälligkeiten, die länger als 14 Tage zurückliegen, lösen kein Ereignis mehr aus. Nutzlast von installment.* ist das Objekt Installment (Rate mit Nummer, Fälligkeit, Betrag und dem vollständigen Ratenplan).
Ereignisse
| Ereignis | Bedeutung | Scope |
|---|---|---|
contact.created | Kontakt angelegt | contacts:read |
contact.updated | Kontakt geändert | contacts:read |
contact.deleted | Kontakt gelöscht | contacts:read |
communication.created | Kommunikation mit einem Kontakt protokolliert | contacts:read |
debt.created | Forderung angelegt | debts:read |
debt.updated | Forderung geändert | debts:read |
debt.phase_changed | Forderung wechselt die Phase (Mahnung, Gericht, Vollstreckung …) | debts:read |
debt.overdue | Forderung ist überfällig geworden (einmal je Fälligkeit) | debts:read |
debt.paid | Forderung vollständig bezahlt | debts:read |
debt.deleted | Forderung gelöscht | debts:read |
payment.received | Zahlung zu einer Forderung erfasst | payments:read |
payment.deleted | Zahlung gelöscht | payments:read |
installment_plan.created | Ratenplan angelegt | payments:read |
installment_plan.updated | Ratenplan geändert (Betrag, Raten, Status) | payments:read |
installment_plan.deleted | Ratenplan gelöscht | payments:read |
installment.due | Rate wird in den nächsten 3 Tagen fällig (einmal je Rate) | payments:read |
installment.missed | Rate bis zur Fälligkeit nicht bezahlt (einmal je Rate) | payments:read |
residence_registry_inquiry.created | Melderegisteranfrage beauftragt (kostenpflichtig) | research:read |
recommendation.created | Empfehlung der Gläubiger-KI erstellt | ai:read |
letter.sent | Brief an Druckdienstleister übergeben | letters:read |
letter.delivered | Brief zugestellt | letters:read |
letter.returned | Brief unzustellbar zurück | letters:read |
letter.failed | Briefversand fehlgeschlagen | letters:read |
invoice.created | Rechnungsentwurf angelegt | invoices:read |
invoice.updated | Rechnungsentwurf geändert | invoices:read |
invoice.finalized | Rechnung festgeschrieben (Nummer vergeben) | invoices:read |
invoice.sent | Rechnung versendet (E-Mail oder Post) | invoices:read |
invoice.partially_paid | Teilzahlung auf Rechnung | invoices:read |
invoice.paid | Rechnung vollständig bezahlt | invoices:read |
invoice.overdue | Rechnung überfällig | invoices:read |
invoice.canceled | Rechnung storniert | invoices:read |
invoice.deleted | Rechnungsentwurf gelöscht | invoices:read |
invoice.handed_to_collection | Rechnung an das Mahnwesen übergeben (Forderung angelegt) | invoices:read |
credit_note.finalized | Gutschrift/Stornorechnung festgeschrieben | invoices:read |
offer.created | Angebot angelegt | offers:read |
offer.sent | Angebot versendet | offers:read |
offer.accepted | Angebot angenommen | offers:read |
offer.rejected | Angebot abgelehnt | offers:read |
offer.expired | Angebot abgelaufen | offers:read |
offer.converted | Angebot in Rechnung/Auftragsbestätigung übernommen | offers:read |
receipt.created | Beleg hochgeladen/empfangen | receipts:read |
receipt.processed | Texterkennung abgeschlossen | receipts:read |
receipt.updated | Beleg geändert | receipts:read |
receipt.booked | Beleg festgeschrieben | receipts:read |
receipt.deleted | Beleg gelöscht | receipts:read |
bank_transaction.imported | Kontoumsatz importiert | banking:read |
bank_transaction.matched | Kontoumsatz einem Beleg/einer Rechnung zugeordnet | banking:read |
project.created | Projekt angelegt | projects:read |
project.updated | Projekt geändert | projects:read |
project.archived | Projekt archiviert | projects:read |
project.deleted | Projekt gelöscht (nur ohne Zeiteinträge) | projects:read |
time_entry.created | Zeiteintrag erfasst | time:read |
time_entry.updated | Zeiteintrag geändert | time:read |
time_entry.deleted | Zeiteintrag gelöscht | time:read |
export.ready | Export (z. B. DATEV) steht zum Download bereit | reports:read |
accounting_period.closed | Buchungszeitraum festgeschrieben (GoBD) | accounting:read |
webhook.test | Testereignis aus den Webhook-Einstellungen | webhooks:read |
Die Schemas aller Ereignisse stehen auch im Abschnitt webhooks der OpenAPI-Beschreibung.