# Fehler (https://developer.bimetrics.de/fehler)

Fehlerformat, HTTP-Status, Fehlercodes und wann sich eine Wiederholung lohnt.

## Format

Fehler kommen als JSON mit HTTP-Status `4xx` oder `5xx`:

```json
{
  "code": "APIRateLimit",
  "status": 429,
  "detail": "Zu viele API-Anfragen. Bitte später erneut versuchen.",
  "context": {}
}
```

| Feld      | Bedeutung                                                                   |
| --------- | --------------------------------------------------------------------------- |
| `code`    | Maschinenlesbarer Fehlercode. Werte deine Logik an `status` und `code` aus. |
| `status`  | Derselbe Wert wie der HTTP-Status.                                          |
| `detail`  | Optionaler Hinweis für Menschen. Der Text kann sich ändern.                 |
| `context` | Optionale Zusatzangaben, je nach Fehler.                                    |

Das Schema heißt `Error` und steht in der [OpenAPI-Beschreibung](https://app.bimetrics.de/api/openapi.json).

## HTTP-Status

| Status | Bedeutung                                                                                                                                                                                                                                                                                                                               | Was tun                                                                        |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `400`  | Ungültige Anfrage, etwa ein unbekanntes Filterattribut, eine unbekannte Filterart (`kind`), ein Filterwert, der nicht zum Typ des Attributs passt, `sort` nach einem nicht sortierbaren Attribut, ein `offset` über dem Höchstwert, eine ID im Pfad, die keine UUID ist, ein Upload ohne `X-Upload-Request-Id` oder eine Datei über 30 MiB | Anfrage korrigieren, nicht wiederholen                                         |
| `401`  | Schlüssel ist ungültig, abgelaufen oder widerrufen oder wurde falsch gesendet (`InvalidAPIKey`), es wurde kein Schlüssel gesendet, oder die angefragte ID gehört zu einer anderen Firma (`Unauthorized`)                                                                                                                                | Schlüssel, Header und ID prüfen, siehe [Authentifizierung](/authentifizierung) |
| `402`  | Für den Aufruf fehlt ein aktiver Tarif oder ein Abo, oder eine Tarifgrenze ist erreicht                                                                                                                                                                                                                                                 | Tarif in der App prüfen                                                        |
| `403`  | Dem Schlüssel fehlt die Berechtigung, oder die API ist für die Firma nicht freigeschaltet                                                                                                                                                                                                                                               | Berechtigung bzw. Tarif prüfen                                                 |
| `404`  | Die Ressource gibt es nicht                                                                                                                                                                                                                                                                                                             | ID prüfen                                                                      |
| `409`  | Die `X-Upload-Request-Id` wurde schon für einen anderen Upload verwendet                                                                                                                                                                                                                                                                | Für einen neuen Beleg eine neue ID wählen, siehe [Beleg-Upload](/beleg-upload) |
| `413`  | Die Anfrage ist größer als erlaubt                                                                                                                                                                                                                                                                                                      | Größe prüfen, siehe [Limits](/limits)                                          |
| `429`  | Zu viele Anfragen                                                                                                                                                                                                                                                                                                                       | Die Sekunden aus dem Header `Retry-After` warten, dann wiederholen             |
| `5xx`  | Vorübergehender Fehler auf unserer Seite                                                                                                                                                                                                                                                                                                | Mit wachsendem Abstand wiederholen                                             |

## Fehlercodes

Die Liste ist nicht abschließend. Es können neue Codes hinzukommen; behandle unbekannte Codes wie ihren HTTP-Status.

| Code                                                   | Status | Bedeutung                                                                                                           |
| ------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------- |
| `InvalidAPIKey`                                        | `401`  | Schlüssel ungültig, abgelaufen, widerrufen oder nicht in genau einem Header gesendet                                |
| `Unauthorized`                                         | `401`  | Kein `bm_`-Schlüssel gesendet, oder die angefragte ID gehört nicht zur Firma des Schlüssels                         |
| `APIKeyPermissionDenied`                               | `403`  | Dem Schlüssel fehlt die Berechtigung für diesen Endpunkt, oder der Endpunkt ist für API-Schlüssel nicht freigegeben |
| `APIUnavailable`                                       | `403`  | Die API ist für die Firma nicht freigeschaltet, etwa ohne gültigen bezahlten Tarif                                  |
| `APIUnavailable`                                       | `500`  | Die API ist vorübergehend nicht verfügbar                                                                           |
| `PlanRequired`, `SubscriptionRequired`, `LimitReached` | `402`  | Tarif, Abo oder Tarifgrenze                                                                                         |
| `BadRequest`                                           | `400`  | Ungültige Anfrage, auch eine ID im Pfad, die keine gültige UUID ist                                                 |
| `NotFound`                                             | `404`  | Nicht gefunden                                                                                                      |
| `UploadRequestConflict`                                | `409`  | Die `X-Upload-Request-Id` gehört zu einem anderen Upload, oder der ursprüngliche Beleg ist gelöscht                 |
| `APIRequestTooLarge`                                   | `413`  | Anfrage zu groß                                                                                                     |
| `APIRateLimit`                                         | `429`  | Zu viele Anfragen                                                                                                   |
| `Internal`                                             | `500`  | Unerwarteter Fehler                                                                                                 |

## Wann wiederholen

Wiederhole nur, wenn der Fehler vorübergehend ist:

* bei `429` nach der Wartezeit aus `Retry-After`,
* bei `5xx`, Zeitüberschreitung oder Verbindungsabbruch mit wachsendem Abstand, zum Beispiel nach 1, 2, 4 und 8 Sekunden.

Uploads wiederholst du mit **derselben** `X-Upload-Request-Id` und derselben Datei. So entsteht auch bei mehreren Versuchen nur ein Beleg.

Bei `400`, `401`, `402`, `403`, `404`, `409` und `413` hilft eine Wiederholung nicht. Prüfe Anfrage, Schlüssel, Berechtigung oder Tarif.
