# Kontakte, Rechnungen und Buchhaltung schreiben (https://developer.bimetrics.de/write-operations)

Scopes, sichere Wiederholungen und Versionsprüfung für schreibende Integrationen.

Schreibzugriff wird je API-Schlüssel ausdrücklich vergeben. Ein bestehender Schlüssel mit `read` oder `upload` erhält dadurch keine Schreibrechte. Die Firma und der Inhaber ergeben sich aus dem Schlüssel; eine Firma lässt sich nicht im Anfrageinhalt auswählen.

## Wiederholungen ohne Duplikate

Sende bei jedem Schreibaufruf den Header `Idempotency-Key` mit einer eindeutigen Kennung deiner fachlichen Aktion, zum Beispiel `order-4711-create-invoice`. Erlaubt sind 1–128 druckbare ASCII-Zeichen ohne Leerzeichen. Bewahre die Kennung zusammen mit dem gesendeten Inhalt auf.

* Wiederhole bei Verbindungsabbruch, Zeitüberschreitung oder einem vorübergehenden Serverfehler exakt denselben Aufruf mit derselben Kennung.
* Für eine neue Aktion verwende eine neue Kennung. Dieselbe Kennung mit anderem Inhalt wird mit `409 IdempotencyConflict` abgelehnt.
* Die Kennung gilt für den Schlüssel, die Firma und die jeweilige Aktion. Wechsle bei einer Wiederholung nicht den Schlüssel.
* Auch eine Wiederholung prüft die aktuelle Berechtigung. Widerrufene Schlüssel können keine früheren Ergebnisse mehr abrufen.

Der Datei-Upload behält seinen eigenen Header `X-Upload-Request-Id`, siehe [Beleg-Upload](/document-upload).

## Gelesenen Stand beibehalten

Lies das Objekt vor einer Änderung. Kontakte und Rechnungsentwürfe erwarten `expectedUpdatedAt` mit dem unveränderten `updatedAt` der Antwort. Speichere den Zeitstempel als Zeichenfolge einschließlich aller Nachkommastellen; eine Umwandlung über eine Datumsfunktion kann Präzision verlieren.

Belegkorrekturen erwarten `expectedVersion` aus dem gelesenen Beleg. Bei Zuordnungen enthält `expectedVersions` die Versionen der betroffenen Objekte gemäß [Referenz](/reference). Verwende diese Werte als undurchsichtige Zeichenfolgen.

Bei `409 VersionConflict` hat sich der fachliche Stand geändert. Lies das Objekt neu und prüfe die beabsichtigte Änderung erneut. Ersetze niemals automatisch die Version und sende denselben Änderungswunsch ungeprüft noch einmal.

## Kontakte

Mit `contacts:write` kannst du Kontakte erstellen und gezielt übergebene Felder ändern. Mit `contacts:read` oder `read` liest du den aktuellen Stand. `externalRef` verbindet den Kontakt mit deiner eigenen Kennung.

Bankverbindungen, steuerliche Kontaktart, Kundennummern sowie Änderungen an USt-IdNr. und Land bleiben der App vorbehalten. Bei bereits verwendeten Kontakten gilt das auch für Name und Anschrift. Die API sendet keine E-Mails an den Kontakt. Prüfe Dublettenhinweise, bevor du erneut anlegst.

## Ausgangsrechnungen

1. Lege mit `invoices:draft` einen EUR-Rechnungsentwurf und einer bestehenden Kontakt-ID an. `externalRef` kann die Bestellnummer deiner Anwendung enthalten.
2. Ergänze und prüfe den gespeicherten Entwurf. Beim Ändern wird der vollständige Entwurfsinhalt gesendet, zusammen mit `expectedUpdatedAt`.
3. Prüfe den Steuerfall. Eine erfolgreiche Vorprüfung ersetzt nicht die abschließende Prüfung der erzeugten E-Rechnung.
4. Mit dem gesonderten Scope `invoices:finalize` schließt du den gespeicherten Stand ab. Im Anfrageinhalt steht ausschließlich `expectedUpdatedAt`. Der Server vergibt die Rechnungsnummer und erzeugt PDF, XML und Buchungsdaten. Es wird keine Nachricht versendet.

Entwürfe werden nicht per API oder Make gelöscht; dafür öffnet der Nutzer bimetrics.

Die API erzeugt ZUGFeRD-Rechnungen mit EN16931-Profil in EUR. Dieser Stand führt keine neue Anrechnung erzeugter Rechnungen ein. Das Dokumentkontingent blockiert weder Festschreiben noch Storno. Festgeschriebene Rechnungen werden nicht überschrieben. Der Storno-Endpunkt erzeugt einen Vollstorno vom Typ 384 aus dem Original; er nimmt keine frei formulierte Gutschrift entgegen.

## Zahlungen zuordnen und erfassen

`matching:write` erlaubt, bestehende Belege und Bankumsätze zuzuordnen oder zulässige Zuordnungen wieder zu lösen. Vor dem Lösen liefert `GET /api/match/:id/delete-preview` die vollständige `expectedVersions`-Map und die IDs dabei gelöschter Serienbelege. Prüfe die Belege und sende die Map im DELETE-Body unverändert. Festgeschriebene Buchungen und Systemzuordnungen für Stornos bleiben geschützt.

Eine bereits erfolgte Bar- oder Verrechnungskontozahlung wird über `POST /api/match/payment` erfasst. Die Neuerfassung ist standardmäßig ausgeschaltet (`manualPaymentsEnabled`). Sende Beleg-ID, aktuelle Version, den zuletzt gelesenen `remainingPaymentMinor` als `expectedAmountOpenMinor`, positiven Betrag in Cent, Zahlungstag und `method` (`cash` oder `clearing`). Der Server bestimmt das passende Konto im Kontenrahmen. Teilbeträge dürfen den noch offenen Betrag nicht überschreiten. Dieser Aufruf löst keine Überweisung aus und erstellt keinen erfundenen Bankumsatz. Sammelbelege, Gutschriften und periodische Belege werden in diesem Ablauf nicht unterstützt.

Ein neuer Idempotency-Key umgeht die Prüfung des offenen Betrags nicht. Eine irrtümliche Erfassung nimmst du mit `POST /api/match/payment/reverse` zurück: `paymentId`, aktuelle Belegversion, aktueller offener Betrag und `reversedOn`. Die Rücknahme bleibt auch bei ausgeschalteter Neuerfassung verfügbar. Sie erzeugt eine Gegenbuchung und erhält Zahlung, Originalbuchung und GoBD-Historie.

## Belege gezielt korrigieren

Mit `documents:write` und `PATCH /api/document/:id` änderst du erlaubte Kopffelder und ausgewählte vorhandene Positionen. Eine Position wird über ihren nullbasierten `index` angesprochen; geändert werden nur Kategorie oder Umsatzsteuersatz. Ausgelassene Felder bleiben erhalten. Das ist kein Ersatz des gesamten Belegs. Festgeschriebene Belege, erstellte Ausgangsrechnungen und geschützte Zuordnungen werden abgelehnt.

## Häufige Konflikte

| Code                      | Behandlung                                                           |
| ------------------------- | -------------------------------------------------------------------- |
| `IdempotencyKeyRequired`  | Stabile Aktionskennung setzen.                                       |
| `IdempotencyConflict`     | Die Kennung gehört zu anderem Inhalt; ursprünglichen Vorgang prüfen. |
| `ExpectedVersionRequired` | Objekt lesen und die zurückgegebene Version mitsenden.               |
| `VersionConflict`         | Neu lesen und die Änderung fachlich erneut prüfen.                   |
| `WriteBudgetExceeded`     | Schreiblimit erreicht; später versuchen.                             |

Weitere fachliche Fehler stehen in der Endpunktreferenz. Bei `4xx` außer `429` hilft eine unveränderte automatische Wiederholung nicht.

## Beispiel: gespeicherten Entwurf abschließen

Nach dem Lesen des Entwurfs sendest du dessen exakten `updatedAt`:

```http
PUT /api/draft/821c3664-640a-4e10-b120-a4ff713532f8/finalize
Authorization: Bearer <API-Schlüssel>
Idempotency-Key: <AKTIONS-ID>
Content-Type: application/json

{"expectedUpdatedAt":"2026-09-01T08:01:02.123456Z"}
```

Bei einem Timeout wiederholst du denselben Aufruf mit demselben Schlüssel und Inhalt. Versionsbedingungen sind für API und MCP Pflicht; ältere Web-Tabs bleiben während des Rollouts kompatibel. Native Make-Module sind unter [Make](/make) beschrieben.
