rescovaKundenintegration · v1.1
OpenAPI herunterladen

Kopiert den Leitfaden und den vollständigen API-Vertrag als Text für ein LLM.

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

  1. API-Schlüssel, Berechtigungen und Organisationsfreischaltung mit Rescova einrichten.
  2. Bei Bedarf Webhook registrieren; Profil auswählen und Kampagne mit Forderungen anlegen.
  3. Prüfbedarf in Rescova bearbeiten und geeignete Kontakte ausdrücklich freigeben.
  4. Gesprächsergebnisse per Webhook oder Ereignisabfrage übernehmen.
  5. 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.