bimetricsEntwickler
Kontakte

Kontakt zusammenführen

Als Markdown ansehen

Benötigte Berechtigung:documents:write(Nicht an DATEV exportierte Belege ändern)

Echte Wirkung

Ändert Daten der Firma; wird atomar mit Idempotenzbeleg und Herkunft protokolliert.
post/api/contact/{id}/merge

Kein Testversand aus der Dokumentation: Dieser Aufruf ist nicht als rein lesend gekennzeichnet. Nutze das Codebeispiel.

Verschiebt die Belege des Kontakts {id} zum Kontakt targetContactId, wie „Mit anderem Kontakt zusammenführen“ in der App, höchstens 50 Belege je Aufruf, die ältesten zuerst; remaining nennt, was danach noch beim Kontakt bleibt. Jeder Beleg bekommt Name, USt-IdNr., IBAN, Adresse und Nummer des Kontakts wie bei counterparty.contactId in PATCH /api/document/{id}, und bimetrics bucht ihn sofort auf das Personenkonto des Kontakts um. Liegt eine Buchung in einem festgeschriebenen Monat, storniert bimetrics sie dort und bucht sie neu; reversedFinalizedMonths nennt die Monate. Ist ein Beleg einem Bankumsatz zugeordnet, bucht bimetrics die ganze Zuordnung neu. Trägt der Beleg genau die Kostenstelle, die am alten Kontakt für neue Belege hinterlegt ist (defaultCostCenterId), oder hat er keine, bekommt er die des neuen Kontakts oder keine. Jede andere bleibt. Übersprungen werden ausgestellte Rechnungen (issued, sie bleiben bei dem Kunden, an den sie gingen), an DATEV exportierte Belege, auch über eine Zuordnung (exported), Belege aus Dauerbuchungen (contract) oder Buchungsvorlagen (linked), Belege einer Zuordnung mit weiteren Belegen (collective, erst die Zuordnung lösen), Belege mit erfasster Bar- oder Privatzahlung (paid), Belege unter „Belegtyp prüfen“ (kindReview), Belege, die danach einen Buchungsfehler hätten, etwa Reverse Charge ohne USt-IdNr. am Kontakt (issues), noch nicht gelesene (reading), stornierte (deleted), Belege, die keine Rechnung und kein Eingangsbeleg sind (otherKind), und Belege, die schon beim Zielkontakt sind (unchanged). Dazu notFound und notPreviewed. Mit deleteSource löscht bimetrics den Kontakt danach, wenn nichts mehr auf ihn verweist, weder ein Beleg noch eine Vorlage, Dauerbuchung, ein Angebot oder ein Entwurf, so wie das Löschen eines Kontakts in der App (sourceDeleted). Ohne deleteSource bleibt er bestehen. Höchstens 50 Belege je Aufruf (400 BulkLimitExceeded). Die Antwort nennt je Beleg, was geschah: change geändert, skipped mit Grund übersprungen, failed mit Code abgelehnt. Das ist ein Teilerfolg wie in der App: Ein abgelehnter Beleg hält die anderen nicht auf, und die Route antwortet mit 200. Mit dryRun ändert sie nichts und zeigt, was geschähe, mit einer version je Beleg. Zum Ausführen gibst du diese als expectedVersions zurück, sonst antwortet die Route mit 400 ExpectedVersionRequired. Es ändert sich nur, was unter change stand und seitdem unverändert ist: Ein geänderter Beleg kommt mit VersionConflict in failed, die übrigen laufen, und ein Beleg ohne Eintrag bleibt mit notPreviewed in skipped. Jeder Beleg läuft als eigener Befehl mit eigenem Eintrag im Protokoll und zählt einzeln auf die Tagesgrenzen der Firma und der Testphase. Der ganze Aufruf zählt einmal auf die Grenzen je Minute. Eine Wiederholung mit gleichem Idempotency-Key ändert nichts doppelt und erledigt, was noch offen ist. Sie klärt auch den Stand, wenn ein Aufruf abbricht: OutcomeUnknown heißt, der Beleg kann schon gebucht sein.

Benötigt einen Schlüssel mit der Berechtigung documents:write.

Authentifizierung

headerAuthentifizierungBearer <bm_…>

Empfohlen: Authorization: Bearer bm_…. Der Schlüssel wird nur einmal angezeigt; nie in URLs, Logs oder Frontend-Code ablegen.

Pfadparameter

id*string

ID des Kontakts, dessen Belege verschoben werden.

Formatuuid

Header-Parameter

Idempotency-Key*string

Stabiler Schlüssel für genau diese Änderung: 1–128 druckbare ASCII-Zeichen ohne Leerzeichen. Bei Wiederholungen denselben Schlüssel und unveränderten Inhalt senden; das Ergebnis wird nicht nochmals erzeugt.

Muster^[!-~]+$
Länge1 <= length <= 128

Request-Body

Zielkontakt, Löschen und Probelauf

application/json
  1. body

Der Kontakt, an den die Belege kommen, und ob der leere Kontakt danach gelöscht wird.

deleteSource?boolean

Den Kontakt {id} danach löschen, wenn nichts mehr auf ihn verweist. Ohne diese Angabe bleibt er bestehen.

dryRun?boolean

Nur zeigen, was geschähe; nichts ändern.

expectedVersions?

Ohne dryRun Pflicht: die version aus change eines dryRun je Beleg-ID. Es ändert sich nur, was seitdem unverändert ist; ein Beleg ohne Eintrag bleibt (notPreviewed).

targetContactId?string

ID des Kontakts, an den die Belege kommen.

Formatuuid

Antworten

Erfolg.

application/json
  1. response

Was mit jedem Beleg des Kontakts geschah oder bei dryRun geschähe.

change?array<>|

Belege, die verschoben werden oder wurden.

dryRun?boolean

True, wenn nichts geändert wurde.

failed?array<>|

Belege, die der Server abgelehnt hat oder ablehnen würde oder deren Stand er nicht bestätigen konnte. Eine Ablehnung ändert nichts.

notice?string

Der Satz zu einer Grenze, die Belege aufgehalten hat, falls es einen gibt.

remaining?integer

Belege, die danach noch beim Kontakt {id} bleiben: übersprungene und solche über 50, die ein weiterer Aufruf verschiebt.

reversedFinalizedMonths?array<string>

Monate (YYYY-MM), in denen bimetrics festgeschriebene Buchungen storniert und mit geändertem Datum, Leistungszeitraum, Konto, Steuerkennzeichen oder Betrag neu gebucht hat. Ändert sich nur der Buchungstext oder die Zuordnung, fehlt der Monat. Hast du die Umsatzsteuer-Voranmeldung für einen dieser Monate oder, bei geändertem Datum, für den neuen Monat schon abgegeben, musst du sie womöglich berichtigen. Fehlt, wenn nichts storniert wurde, und bei einer Wiederholung mit demselben Idempotency-Key.

skipped?array<>|

Belege, die am Kontakt {id} bleiben, mit Grund.

sourceDeleted?boolean

True, wenn der Kontakt {id} gelöscht wurde.

totalMinor?integer

Summe von change in Cent.

Beispielanfrage
curl --fail-with-body "https://app.bimetrics.de/api/contact/497f6eca-6276-4993-bfeb-53cbbbba6f08/merge" \  -H "Authorization: Bearer $BIMETRICS_API_KEY" \  -H "Idempotency-Key: rechnung-2026-001" \  -H "Content-Type: application/json" \  -d '{}'
Beispielantwort
{  "change": [    {      "amountMinor": 11900,      "counterparty": "Beispiel Bürobedarf GmbH",      "id": "a129ef0a-da5d-4204-804c-764d751bca95",      "invoiceNumber": "RE-2026-0142"    }  ],  "dryRun": false,  "failed": [],  "remaining": 0,  "skipped": [],  "sourceDeleted": true,  "totalMinor": 11900}