Rescova API – Integrationsleitfaden
Stand: 31.10.2026 · API-Vertrag 1.2.0 · Basis-URL: https://api.rescova.de
Übergeben Sie Schuldner und Forderungen, starten Sie Kampagnen und übernehmen Sie Gesprächsergebnisse. Ihr System meldet bestätigte Zahlungseingänge; Rescova aktualisiert damit den Forderungsstand und die weitere Bearbeitung.
Öffentliche Dokumentation: app.rescova.de/docs. Alle Felddefinitionen, Grenzwerte und Antwortformate stehen in der OpenAPI-Datei.
1. Ablauf und Zugang
- API-Schlüssel, Berechtigungen und Organisationsfreischaltung mit Rescova einrichten.
- Bei Bedarf Webhook registrieren; Profil auswählen und Kampagne mit Forderungen anlegen.
- Prüfbedarf in Rescova bearbeiten und geeignete Kontakte ausdrücklich freigeben.
- Gesprächsergebnisse per Webhook oder Ereignisabfrage übernehmen.
- Bestätigte Zahlungen melden und aktuelle Forderungsstände abgleichen.
Den API-Zugang richten wir mit Ihrem technischen Ansprechpartner ein, nachdem Ihre Organisation und die benötigten Berechtigungen freigegeben wurden. Den Schlüssel erhalten Sie einmalig über einen sicheren Kanal. Verwenden Sie ihn ausschließlich serverseitig, niemals in URLs, Browsercode oder Protokollen:
Authorization: Bearer <api-key>
Alternativ ist x-api-key: <api-key> möglich. Die Organisation ergibt sich aus dem
Schlüssel; übergeben Sie keine customer_id. Daten und Webhooks sind an den
ursprünglichen Schlüssel gebunden. Stimmen Sie Schlüsselwechsel mit Rescova ab;
ein neuer Schlüssel übernimmt den Zugriff nicht automatisch.
Begriffe: Ein contact ist ein Schuldnerkontakt, ein case eine Forderung.
Eine API-Kampagne ist ein benannter Importbestand. Dessen import_id ist zugleich
die Kampagnen-ID. Ihre stabilen Referenzen heißen contact_external_ref und
case_external_ref.
2. Endpoints
| Methode | Pfad | Funktion | Berechtigung |
|---|---|---|---|
| GET | /v1/contact-imports/profiles |
Absender-/Zahlungsprofile lesen | contacts:import |
| POST | /v1/campaigns |
Kampagne mit Kontakten und Forderungen anlegen | contacts:import |
| GET | /v1/campaigns/{import_id} |
Importstatus und aktuelle Bearbeitungszähler lesen | imports:read |
| POST | /v1/campaigns/{import_id}/start |
Geeignete Kontakte zum Anrufen freigeben | campaigns:start |
| GET / PATCH | /v1/contacts/{contact_external_ref} |
Schuldnerkontakt lesen / korrigieren | contacts:read / contacts:write |
| GET / PATCH | /v1/cases/{case_external_ref} |
Forderungsstand lesen / Metadaten korrigieren | cases:read / cases:write |
| POST | /v1/payments |
Bestätigten Zahlungseingang buchen | payments:write |
| GET | /v1/payments/{payment_id} |
Gespeicherten Zahlungsbeleg lesen | payments:read |
| GET | /v1/integration-events |
Gesprächsergebnisse und Zusammenfassungen abrufen | events:read |
| GET / POST | /v1/webhook-endpoints |
Webhook-Ziele auflisten / registrieren | webhooks:manage |
| POST | /v1/webhook-endpoints/{endpoint_id}/rotate-secret |
Webhook-Signaturschlüssel ersetzen | webhooks:manage |
| DELETE | /v1/webhook-endpoints/{endpoint_id} |
Webhook-Ziel deaktivieren | webhooks:manage |
POST /v1/contact-imports und GET /v1/contact-imports/{import_id} sind gleichwertige
Alternativen zu Kampagnenanlage und Statusabfrage. Sie verwenden dieselben Daten,
Berechtigungen und Idempotenzschlüssel; legen Sie denselben Bestand nicht doppelt an.
3. Kampagne anlegen und starten
Ein Zahlungsprofil enthält den Absendernamen für Gespräche und die zugehörigen Zahlungsdaten, etwa Zahlungsempfänger und IBAN. Sie verwalten Profile in der Plattform unter Wissensdatenbank und wählen bei der Kampagnenanlage per API das passende Profil aus. Die Kampagne speichert eine feste Kopie; spätere Profiländerungen verändern bestehende Kampagnen nicht.
Lesen Sie zuerst GET /v1/contact-imports/profiles. Die Antwort enthält profiles
mit id, name, display_name und version, keine Bankdaten. Bei mehreren aktiven
Profilen ist communication_profile_id erforderlich; bei genau einem wird es
automatisch ausgewählt. Die optionale communication_profile_version schützt
gegen zwischenzeitliche Profiländerungen.
Beispiel: ein Bestand mit einer Forderung über 150,00 EUR. Verwenden Sie Ihr gewähltes Profil und echte Datensätze; die folgenden Werte sind Beispieldaten.
POST /v1/campaigns
Authorization: Bearer <api-key>
Idempotency-Key: erp-campaign-20261031-0001
Content-Type: application/json
{
"name": "Offene Forderungen Oktober 2026",
"communication_profile_id": "42",
"communication_profile_version": 3,
"records": [{
"contact_external_ref": "debtor-0042",
"name": "Erika Beispiel",
"phone_e164": "+4917612345678",
"email": "erika@example.org",
"case_external_ref": "claim-1042",
"invoice_number": "RE-1042",
"creditor_name": "Beispielhandel GmbH",
"amount_cents": 15000,
"due_date": "2026-09-30"
}]
}
Antwort: 201 Created, bei identischer Wiederholung 200 OK:
{
"import_id": "123",
"imported_records": 1,
"total_records": 1,
"rejected_records": 0,
"errors": [],
"replayed": false,
"scheduled_shadow_jobs": 1,
"unchanged_records": 0,
"review_required": 0,
"executable_call_jobs": 0
}
Jeder Datensatz benötigt Kontaktreferenz, Name, internationale Telefonnummer,
Forderungsreferenz, Rechnungsnummer, Gläubigernamen (creditor_name), positiven
Centbetrag und Fälligkeit. Der Gläubiger ist der ursprüngliche Forderungsinhaber;
er kann vom Inkassounternehmen und Zahlungsempfänger abweichen.
Optional sind email, file_number, sub_file_number und note.
Beträge sind ganze Cent in EUR; beim Import gibt es kein Feld currency.
Datumsformat: YYYY-MM-DD. Unbekannte Eingabefelder werden abgelehnt.
Ein Request umfasst 1–10.000 Datensätze und höchstens 16 MiB JSON (maximal 64
Verschachtelungsebenen, sonst 400 payload_too_deep). Gültige Kontakte
werden übernommen, ungültige zurückgemeldet. Prüfen Sie auch bei 201 immer
rejected_records und errors. Jeder Fehler nennt die Position in records
(row, beginnend bei 1), das Feld, einen Fehlercode und eine verständliche Meldung:
{
"row": 2,
"case_external_ref": "claim-1043",
"field": "creditor_name",
"code": "creditor_name_required",
"message": "Gläubiger fehlt. Bitte den Namen des ursprünglichen Gläubigers angeben."
}
Gläubigernamen dürfen nach Bereinigung bis zu 200 Unicode-Zeichen lang sein. Internationale Schriftzeichen, Umlaute und übliche Sonderzeichen sind erlaubt; Leerraum wird bereinigt. Fehlend, leer, falscher Datentyp, reine Platzhalter wie „–“, Steuerzeichen und Überlänge werden abgelehnt. Es gibt keinen Firmenrechtsform- oder Wörterbuchfilter.
Mehrere Forderungen mit derselben Kontaktreferenz oder Telefonnummer werden
gemeinsam behandelt: Ist eine Zeile fehlerhaft, wird die gesamte betroffene
Kontaktgruppe zurückgemeldet. Andere Kontakte werden weiter übernommen.
Doppelte Forderungsreferenzen werden zurückgewiesen. Korrigieren Sie die
zurückgemeldeten Kontaktgruppen und senden Sie sie mit einem neuen Idempotenzschlüssel.
Sind alle Zeilen ungültig, antwortet die API mit 400 no_valid_records und den
Fehlern, ohne einen Bestand anzulegen; bei ausschließlich bestehenden Datenkonflikten
kann 409 folgen. Fehler am Zugang, Profil, an Berechtigungen oder den allgemeinen
Request-Einstellungen betreffen weiterhin den gesamten Request. Technische Fehler
rollen den gesamten Vorgang zurück.
Identische Wiederholungen liefern dasselbe Importergebnis einschließlich Fehlern; verändern Sie dabei auch abgelehnte Zeilen nicht. Alte erfolgreich gespeicherte Imports ohne Gläubiger bleiben unverändert wiederholbar. Ein Reimport überschreibt keine bestehenden Forderungen: Für Änderungen verwenden Sie PATCH. Zusätzliche Forderungen zu bereits anderen Beständen zugeordneten Kontakten müssen separat geprüft werden und können als Konflikt zurückgemeldet werden.
calling_overrides setzt optionale Anrufregeln; fehlende Werte folgen den
Organisationsvorgaben. payment_overrides legt die Zahlungsregeln des Bestands fest:
Ohne Angabe sind Raten und Rabatte deaktiviert. Aktivierte Raten benötigen
max_installments (2–24). Zahlungsregeln und gewähltes Profil werden bei Anlage
festgehalten. Details stehen in OpenAPI.
Anlegen startet keine Anrufe. GET /v1/campaigns/123 liefert Importstatus und
Zähler, keine einzelnen Datensätze. review_required beschreibt den Prüfbedarf
bei Anlage; current_review_required und executable_call_jobs den aktuellen Stand.
Vorbereitete scheduled_shadow_jobs sind noch nicht ausführbar.
Die Statusabfrage liefert auch die gespeicherten Zeilenfehler unter errors.
Nach erforderlicher Prüfung starten Sie separat:
POST /v1/campaigns/123/start
Authorization: Bearer <api-key>
Idempotency-Key: erp-campaign-start-20261031-0001
Content-Type: application/json
{ "confirm": true }
Die Antwort enthält released_contacts, blocked_contacts, blocked_reasons,
organization_state und replayed. Ein erfolgreicher Request kann null Kontakte
freigeben. Bei blocked_reasons.phone_check_pending warten Sie die Telefonprüfung
ab und starten danach ausdrücklich mit einem neuen Idempotenzschlüssel.
Der Start setzt die eingerichtete Anruffreigabe der Organisation voraus und
umgeht keine Sperren, Prüfpflichten, Vereinbarungen oder Versuchslimits. Er gibt
Kontakte an die Planung frei; er bestätigt keine sofortige Verbindung.
Bei 409 organization_resume_requires_review muss die gemeinsame Automatisierung
in Rescova geprüft werden. Pausieren erfolgt in Rescova. Ein Replay eines früheren
Starts hebt eine spätere Pause nicht auf.
4. Zahlungseingänge melden
Ihr System ist die Quelle für bestätigte Zahlungseingänge. Eine Zahlungszusage, die Aussage „bereits bezahlt“ oder eine ausgelöste Überweisung belegt noch keinen gebuchten Eingang. Ein automatischer Kontoumsatzabruf ist nicht Teil dieser API.
POST /v1/payments
Authorization: Bearer <api-key>
Idempotency-Key: erp-payment-20261031-0001
Content-Type: application/json
{
"external_payment_ref": "bank-transaction-4711",
"case_external_ref": "claim-1042",
"amount_cents": 5000,
"currency": "EUR",
"paid_date": "2026-10-31"
}
Alle fünf Felder sind Pflicht. external_payment_ref ist innerhalb Ihrer Organisation
eindeutig (maximal 160 Zeichen). Betrag: positive ganze Cent; Währung: EUR.
paid_date darf nicht in der Zukunft liegen. Optional: note, maximal 500 Zeichen.
Maximaler Body: 16 KiB.
Antwort: 201 Created, bei identischer Wiederholung 200 OK:
{
"id": "pay_0123456789abcdef0123456789abcdef",
"external_payment_ref": "bank-transaction-4711",
"case_external_ref": "claim-1042",
"amount_cents": 5000,
"currency": "EUR",
"paid_date": "2026-10-31",
"payment_plan_id": null,
"installment_number": null,
"outstanding_amount_cents": 10000,
"case_state": "CONTACTABLE",
"recorded_at": "2026-10-31T10:15:00.000Z",
"replayed": false
}
Teilzahlungen reduzieren den Saldo. Vollständige Zahlungen setzen die Forderung
auf PAID und beenden passende noch nicht gestartete Anrufjobs. Laufende Gespräche
und bereits abgeschickte Nachrichten werden nicht zurückgerufen.
Ratenpläne: Lesen Sie zuerst den Plan über die Forderungsabfrage. Bei einem
bestehenden zahlbaren Plan sind zusätzlich payment_plan_id als Zeichenkette und
installment_number als positive Ganzzahl nötig. Ein POST bucht genau eine ganze
Rate zum gespeicherten Betrag, einschließlich Gebühren und abweichender Schlussrate.
Mehrere Raten benötigen getrennte Zuordnungen und jeweils eindeutige Zahlungsreferenzen;
alternativ ist manueller Abgleich nötig. pending_approval ist noch nicht zahlbar.
Bei needs_reconciliation: true oder unvollständigem Ratenplan ist zunächst
fachlicher Abgleich nötig. Teilzahlungen innerhalb einer Rate, Überzahlungen und
Stornos werden in dieser Version nicht als freie API-Buchungen unterstützt.
GET /v1/payments/{payment_id} erwartet die zurückgegebene id mit Präfix pay_.
Das numerische payment_id im Ratenplan ist eine andere Buchungsreferenz.
Der Beleg bleibt eine Momentaufnahme zum Buchungszeitpunkt und enthält beim Lesen
kein replayed. Den aktuellen Saldo lesen Sie über die Forderung.
5. Daten lesen und korrigieren
GET /v1/contacts/{contact_external_ref} liefert Name, Telefonnummer, E-Mail und
Version. GET /v1/cases/{case_external_ref} liefert Forderungsdaten, aktuellen Saldo,
Status, payment_commitment und payment_plan, jeweils Objekt oder null.
Vereinbarungen können historisch sein: Prüfen Sie deren Status. Der Ratenplan
enthält installment_schedule; bei schedule_complete: false dürfen fehlende
Raten nicht ergänzt oder geraten werden.
Übernehmen Sie Kontaktreferenzen exakt, einschließlich Groß-/Kleinschreibung. Forderungsreferenzen werden ohne Beachtung der Groß-/Kleinschreibung abgeglichen. Kodieren Sie Referenzen als URL-Pfadsegment. Zugriff besteht nur auf Daten des ursprünglichen API-Imports dieses Schlüssels.
Lesen Sie vor einer Korrektur die aktuelle version und übergeben Sie sie
unverändert als Zeichenkette in expected_version:
PATCH /v1/cases/claim-1042
Authorization: Bearer <api-key>
Content-Type: application/json
{
"expected_version": "5",
"due_date": "2026-11-15",
"note": "Fälligkeit mit dem Kunden abgestimmt"
}
| Ressource | Änderbare Felder |
|---|---|
| Kontakt | name, email; eine geänderte Telefonnummer wird mit 409 phone_change_requires_manual_review abgelehnt |
| Forderung | invoice_number, due_date, file_number, sub_file_number, creditor_name, note |
Optionale Textfelder und E-Mail lassen sich mit null entfernen. Saldo, Originalbetrag,
Status, Referenzen und Zahlungsregeln sind keine PATCH-Felder. Maximaler Body: 16 KiB.
Korrekturen benötigen auch die organisationsseitige API-Importfreischaltung.
Die Antwort enthält den Datensatz sowie version, changed und
calling_release_required. Änderungen an Namen oder Forderungsmetadaten halten
noch nicht gestartete Anrufjobs an und benötigen ggf. Prüfung und erneute Freigabe.
E-Mail-Korrekturen allein erhalten die Anrufplanung. Laufende Anrufe, ausstehende
Gesprächsfinalisierung oder mehrdeutige Zuordnungen können Korrekturen mit 409 blockieren.
Alternativ zu expected_version ist If-Match: "5" möglich. Ohne Vorbedingung folgt
428, bei veraltetem Stand 412: erneut lesen und prüfen. Kontaktabfragen liefern
einen Versions-ETag. Forderungsabfragen liefern immer den aktuellen Body ohne
ETag/304. Die Version schützt Metadatenkorrekturen; sie ist kein Änderungszeiger
für Zahlungsvereinbarungen. PATCH verwendet keinen Idempotenzschlüssel.
6. Gesprächsergebnisse und Webhooks
GET /v1/integration-events?limit=50
Authorization: Bearer <api-key>
Die Antwort enthält data (Ereignisse), has_more und next_cursor. Der einzige
Ereignistyp ist call.outcome.finalized. Er enthält Kontakt-/Forderungsreferenz,
Gesprächsdaten und, falls vorhanden, resolution.payment_commitment,
resolution.payment_plan oder resolution.callback. Fehlende Werte werden weggelassen;
resolution kann leer sein. human_review_required: true verlangt fachliche Prüfung.
Verarbeiten Sie Statuswerte als erweiterbare Zeichenketten.
Gesprächszusammenfassungen abrufen: Das Feld data[].data.call.summary
enthält eine kurze textliche Zusammenfassung des Gesprächs.
Sie wird nach erfolgreicher Nachbearbeitung bereitgestellt und kann fehlen,
wenn keine belastbare Zusammenfassung vorliegt. Beispiel einer Ereignisseite:
{
"data": [{
"id": "evt_0123456789abcdef0123456789abcdef",
"type": "call.outcome.finalized",
"schema_version": 1,
"occurred_at": "2026-10-31T10:20:00.000Z",
"data": {
"import_id": "123",
"contact": { "external_ref": "debtor-0042" },
"case": {
"external_ref": "claim-1042",
"invoice_number": "RE-1042",
"state": "CONTACTABLE",
"outstanding_amount_cents": 10000,
"currency": "EUR",
"disputed": false
},
"call": {
"attempt_id": "456",
"connected_duration_seconds": 60,
"summary": "Die Forderung wurde besprochen. Die angerufene Person wünscht eine schriftliche Übersicht.",
"human_review_required": false
},
"resolution": {}
}
}],
"has_more": false,
"next_cursor": null
}
Ereignisse sind unveränderliche Gesprächsmomentaufnahmen. Spätere Zahlungen, Planfreigaben oder Widerrufe erzeugen derzeit keine eigenen Ereignisse. Auch spätere Zusammenfassungskorrekturen ändern das gespeicherte Ereignis nicht. Den aktuellen Zahlungs- und Vereinbarungsstand lesen Sie über die Forderung. Der Feed umfasst die direkt zugeordneten Anrufe eigener API-Importe, nicht sämtliche Anrufe der Organisation oder eine vollständige Historie eingehender Anrufe und Demos.
Fortlaufend abrufen: limit ist 1–100 (Standard 50). Solange has_more: true
ist, übernehmen Sie next_cursor unverändert. Speichern Sie den Fortschritt erst
nach dauerhafter Verarbeitung und deduplizieren Sie anhand von event.id.
Die letzte Seite liefert next_cursor: null: Behalten Sie den Cursor, mit dem Sie
diese Seite angefordert haben, und pollen Sie später wieder ab dort. Ohne bisherigen
Cursor starten Sie erneut ohne Cursor. Wiederholte Ereignisse sind dadurch zu erwarten.
Alternativ oder ergänzend registrieren Sie ein Webhook-Ziel:
POST /v1/webhook-endpoints
Authorization: Bearer <api-key>
Content-Type: application/json
{
"url": "https://erp.example.org/rescova/events",
"events": ["call.outcome.finalized"]
}
Zulässig sind öffentliche HTTPS-Ziele auf Port 443, maximal zehn aktive Ziele pro
Schlüssel. Die Antwort liefert signing_secret einmalig. Neue Ziele erhalten nur
zukünftige Ereignisse. Eine aktive URL erneut anzulegen liefert 409; eine
deaktivierte URL wird mit neuem Secret reaktiviert (200).
Webhooks enthalten das einzelne Ereignisobjekt ohne die Seitenhülle des Feeds.
Prüfen Sie X-Rescova-Signature gegen die unveränderten Request-Bytes:
"v1=" + hex(HMAC-SHA256(signing_secret, X-Rescova-Timestamp + "." + raw_request_body))
Verwenden Sie das gesamte Secret einschließlich whsec_ als UTF-8-Schlüssel.
Vergleichen Sie zeitkonstant, prüfen Sie den Unix-Zeitstempel in Sekunden innerhalb
eines engen Fensters (z. B. ± fünf Minuten) und gleichen Sie X-Rescova-Event-Id
und X-Rescova-Event-Type mit dem Body ab. Deduplizieren Sie anhand der Ereignis-ID.
Bestätigen Sie die dauerhafte Annahme innerhalb von zehn Sekunden mit 2xx.
Netzwerkfehler, 408, 425, 429 und 5xx lösen regulär bis zu acht Versuche aus;
geplante Wartezeiten: 1 min, 5 min, 30 min, 2 h, 6 h, 24 h und 48 h.
Wiederherstellung nach Abbrüchen kann zusätzliche Zustellungen erzeugen.
Andere 4xx und 3xx beenden die Zustellung; Weiterleitungen werden nicht verfolgt.
Mehrfache und ungeordnete Zustellung ist möglich. Den Feed nutzen Sie zum Nachholen.
Die Zielliste enthält keine Secrets. Rotation ersetzt das Secret ohne garantierte
Übergangsfrist. Deaktivieren liefert 204, erneut deaktivieren 404; ausstehende
Zustellungen werden beendet, laufende können noch eintreffen.
7. Wiederholungen und Fehler
Import, Kampagnenstart und Zahlung benötigen einen Idempotency-Key: 16–128 Zeichen
aus A–Z, a–z, 0–9, ., _, :, -. Verwenden Sie getrennte Schlüssel für
die drei Aktionen. Wiederholen Sie bei unklarem Ergebnis denselben Request mit
demselben Schlüssel unverändert. Ein Replay enthält replayed: true und führt die
Aktion nicht erneut aus. Derselbe Schlüssel mit anderem Inhalt liefert 409.
Zahlungen sind zusätzlich über external_payment_ref innerhalb der Organisation
gegen Doppelbuchung geschützt, auch über Schlüsselwechsel hinweg. Unterschiedliche
Referenzen für denselben realen Eingang müssen Sie im Quellsystem verhindern.
Ein gespeicherter fehlgeschlagener Import kann seinen Schlüssel verbrauchen:
Bei idempotency_key_previously_failed korrigieren Sie die Ursache und verwenden einen neuen.
| HTTP | Reaktion |
|---|---|
| 400 | Felder, Formate oder Parameter korrigieren |
| 401 / 403 | Schlüssel, Berechtigungen und Freischaltung prüfen |
| 404 | Referenz und ursprünglichen API-Schlüssel prüfen |
| 409 | Fachlichen Konflikt prüfen; nicht unverändert endlos wiederholen |
| 412 / 428 | Datensatz erneut lesen bzw. Versionsvorbedingung ergänzen |
| 413 | Request verkleinern |
| 429 / 500 / 503 | Mit wachsender Wartezeit und Zufallsanteil wiederholen; Idempotenz erhalten |
Fachliche Fehler haben die Form { "error": "fehlercode" }. Parser- und Proxyfehler
können davon abweichen; prüfen Sie HTTP-Status und Content-Type. Neue Importversuche
sind auf 20 gespeicherte Importe pro rollierender Minute und Schlüssel begrenzt;
Fehlversuche können mitzählen. Ein Retry-After-Header ist nicht garantiert.
Nach verlorenem PATCH-Response lesen Sie den Datensatz erneut und gleichen den Stand ab. Nach verlorener Webhook-Registrierungsantwort prüfen Sie die Zielliste und rotieren bei Bedarf das Secret; diese Aktionen verwenden keinen Idempotenzschlüssel.
Umfang: Keine öffentliche Gesamtliste aller Kontakte/Forderungen, kein API-Pausieren, keine Zahlungsstornos und keine eigenen Änderungsereignisse für Zahlungen oder Pläne.