# Kostenstelle für mehrere Belege setzen (https://developer.bimetrics.de/reference/documents/set-document-cost-center-in-bulk)

`POST https://app.bimetrics.de/api/document/bulk/cost-center`

operationId: `setDocumentCostCenterInBulk` · Berechtigung (Scope): `documents:write` · Bereich: Belege

Setzt an jedem genannten Beleg eine Kostenstelle oder Verteilung wie der Button „Kostenstelle“ in der Mehrfachauswahl der App; ein leerer String entfernt sie, ohne `costCenterId` antwortet die Route mit `400`. Weil sich kein Betrag ändert, geht das auch bei ausgestellten und bezahlten Belegen. bimetrics bucht jeden geänderten Beleg sofort neu. Übersprungen werden festgeschriebene (`finalized`), an DATEV exportierte (`exported`), gelöschte (`deleted`) und noch nicht gelesene Belege (`unread`) sowie Belege, die sie schon haben (`unchanged`); dazu kommen `notFound` und `notPreviewed`. Die Kostenstelle festgeschriebener Belege lässt sich einzeln mit `PATCH /api/document/{id}` trotzdem ändern, solange sie nicht an DATEV exportiert sind; dann storniert bimetrics die Buchungen und bucht sie neu. Eine archivierte oder unbekannte Kostenstelle lehnt die Route für alle Belege ab (`409 CostCenterRejected` bzw. `404 CostCenterNotFound`). 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`.

> **Achtung:** Ändert Daten der Firma; wird atomar mit Idempotenzbeleg und Herkunft protokolliert.
>
> KI-Agenten fragen vor diesem Aufruf beim Nutzer nach.

### Authentifizierung

`Authorization: Bearer bm_…` (alternativ `X-API-KEY: bm_…`, nie beide zugleich).

### Parameter

| Name | Ort | Pflicht | Typ | Beschreibung |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | ja | 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. |

### Request-Body (`application/json`)

Belege, Kostenstelle und Probelauf

Schema `BulkCostCenterRequest`.

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `costCenterId` | string, kann null sein | Pflicht: ID einer Kostenstelle oder Verteilung der Firma, die nicht archiviert ist; ein leerer String entfernt sie. |
| `documentIds` | Array<string (uuid)>, kann null sein | IDs der Belege, 1 bis 50. |
| `dryRun` | boolean | Nur zeigen, was geschähe; nichts ändern. |
| `expectedVersions` | object | 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`). |

### Beispiel

```sh
curl --fail-with-body "https://app.bimetrics.de/api/document/bulk/cost-center" \
  -H "Authorization: Bearer $BIMETRICS_API_KEY" \
  -H "Idempotency-Key: rechnung-2026-001" \
  -H "Content-Type: application/json" \
  -d '{"kind":"and","children":[],"limit":50,"offset":0}'
```

### Antworten

| Status | Beschreibung | Inhalt |
| --- | --- | --- |
| 200 | Erfolg. | `application/json`: BulkResult |
| 400 | Ungültige Anfrage, z. B. ein Parameter mit ungültigem Wert wie eine ID, die keine UUID ist; korrigieren statt wiederholen. Mehr unter [Fehler](https://developer.bimetrics.de/errors). | `application/json`: Error |
| 401 | Kein gültiger Schlüssel: fehlt (`Unauthorized`), ist unbekannt, abgelaufen oder widerrufen oder wurde nicht in genau einem Header gesendet (`InvalidAPIKey`). Schlüssel prüfen, nicht wiederholen. Auch eine ID, die zu einer anderen Firma gehört, ergibt `401 Unauthorized`. | `application/json`: Error |
| 403 | Dem Schlüssel fehlt die Berechtigung für diese Route (`APIKeyPermissionDenied`), oder die Firma hat keinen API-Zugang (mehr), etwa nach Ende der Testphase oder des Abos (`APIUnavailable`). | `application/json`: Error |
| 404 | Nicht gefunden (`NotFound`). | `application/json`: Error |
| 409 | Versionskonflikt (`VersionConflict`), abweichender Inhalt für denselben Idempotency-Key (`IdempotencyConflict`), Dublette (`ContactDuplicate`) oder fachlich gesperrte Änderung. Aktuellen Zustand laden und prüfen; keinen anderen Schlüssel verwenden, um einen Konflikt zu umgehen. | `application/json`: Error |
| 413 | Die Anfrage ist zu groß (`APIRequestTooLarge`), siehe `x-bimetrics-limits`. | `application/json`: Error |
| 429 | Zu viele Anfragen; nach `Retry-After` Sekunden erneut senden. Mehr unter [Fehler](https://developer.bimetrics.de/errors). (Header: Retry-After) | `application/json`: Error |
| 500 | Serverfehler; die Anfrage später wiederholen. Mehr unter [Fehler](https://developer.bimetrics.de/errors). | `application/json`: Error |

#### Felder der Antwort 200 (`BulkResult`)

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `change` | Array<BulkChange>, kann null sein | Belege, die sich ändern oder geändert haben. |
| `dryRun` | boolean | True, wenn nichts geändert wurde. |
| `failed` | Array<BulkFailure>, kann null sein | 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. |
| `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<BulkSkip>, kann null sein | Belege, die bleiben, wie sie sind. |
| `totalMinor` | integer | Summe von `change` in Cent. |

Verschachtelte Schemas stehen vollständig in der OpenAPI-Beschreibung: https://app.bimetrics.de/api/openapi.json
