# Mehrere Rechnungen auf einmal mahnen (https://developer.bimetrics.de/reference/receivables/run-reminders)

`POST https://app.bimetrics.de/api/reminder/bulk`

operationId: `runReminders` · Berechtigung (Scope): `invoices:draft` · Bereich: Forderungen und Mahnungen

Stellt für bis zu 25 überfällige Rechnungen je eine Mahnung der nächsten Stufe aus, wie der Mahnlauf in der App: Frist, Text und Mahngebühr aus den Einstellungen der Stufe, Verzugszinsen und Pauschale nach den Schaltern der Firma, Ausstellungsdatum heute. Jede Mahnung bekommt Nummer, Original-PDF und Forderungssnapshot wie bei `issueReminder`. Keine Buchung, kein Versand. Übersprungen werden stornierte Rechnungen (`cancelled`), solche mit ungeklärter Zahlung (`payment_unknown`), bezahlte (`settled`), mit Mahnsperre (`reminder_hold`), ohne Fälligkeit (`due_date_missing`), nicht überfällige (`not_overdue`), mit laufender Frist einer ausgestellten Mahnung (`active_reminder`), in den 3 Tagen danach (`reminder_wait`, siehe `remindAgainOn`), nach der 3. Mahnung (`levels_done`) und mit offenem Mahnungsentwurf (`open_draft`). Dazu `not_found` und `not_previewed`. Höchstens 25 Rechnungen je Aufruf (`400 BulkLimitExceeded`). Die Antwort nennt je Rechnung, was geschah: `change` ausgestellt, `skipped` mit Grund übersprungen, `failed` mit Code abgelehnt. Das ist ein Teilerfolg wie in der App, die Route antwortet mit `200`. Mit `dryRun` stellt sie nichts aus und zeigt Stufe, Frist und Beträge mit einer `version` je Rechnung. Zum Ausstellen gibst du diese als `expectedVersions` zurück, sonst antwortet die Route mit `400 ExpectedVersionRequired`. Es wird nur ausgestellt, was unter `change` stand und noch so aussieht: Hat sich eine Rechnung seit dem `dryRun` geändert, oder wären ihre Beträge heute andere (etwa nach Mitternacht), kommt sie mit `VersionConflict` in `failed`; die übrigen laufen. Jede Rechnung läuft als eigener Befehl mit eigenem Eintrag im Protokoll und zählt einzeln auf die Tagesgrenzen der Firma und der Testphase. Ein Idempotency-Key gilt für den ganzen Lauf, auch über mehrere Aufrufe: Eine Wiederholung stellt nichts doppelt aus und erledigt, was noch offen ist. `OutcomeUnknown` heißt, die Mahnung kann schon ausgestellt sein; eine Wiederholung mit demselben Key klärt das.

Benötigt einen Schlüssel mit der Berechtigung `invoices:draft`.

> **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`)

Rechnungen und Probelauf

Schema `ReminderRunRequest`.

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `dryRun` | boolean | Nur zeigen, was ausgestellt würde; nichts ändern. |
| `expectedVersions` | object | Ohne `dryRun` Pflicht: die `version` aus `change` eines `dryRun` je Rechnungs-ID. Ausgestellt wird nur, was noch so aussieht; eine Rechnung ohne Eintrag bleibt (`not_previewed`). |
| `sourceDraftIds` | Array<string (uuid)>, kann null sein | IDs der Rechnungen (`sourceDraftId` der Forderung), 1 bis 25. |

### Beispiel

```sh
curl --fail-with-body "https://app.bimetrics.de/api/reminder/bulk" \
  -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`: ReminderRunResult |
| 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 |
| 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 (`ReminderRunResult`)

| Feld | Typ | Beschreibung |
| --- | --- | --- |
| `change` | Array<ReminderRunItem>, kann null sein | Mahnungen, die ausgestellt würden oder wurden. |
| `dryRun` | boolean | True, wenn nichts ausgestellt wurde. |
| `failed` | Array<ReminderRunFailure>, kann null sein | Rechnungen, die der Server abgelehnt hat oder ablehnen würde oder deren Stand er nicht bestätigen konnte. Eine Ablehnung stellt nichts aus. |
| `notice` | string | Der Satz zu einer Grenze, die Rechnungen aufgehalten hat, falls es einen gibt. |
| `openMinor` | integer | Summe der offenen Beträge von `change` in Cent. |
| `skipped` | Array<ReminderRunSkip>, kann null sein | Rechnungen ohne Mahnung, mit Grund. |
| `totalMinor` | integer | Summe der Gesamtbeträge von `change` in Cent. |

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