# Fehler

> Die Fehlerstruktur, jeder Fehlercode und wie man sicher wiederholt.

Fehler verwenden normale HTTP-Statuscodes und einen JSON-Body mit einem stabilen `code`, den Sie in Ihrem Code überprüfen können, und einen `message`, der für Menschen geschrieben ist.

```json
{
  "error": {
    "code": "validation_error",
    "message": "Some fields are invalid.",
    "issues": [
      {
        "path": "products.0.listPrice",
        "message": "Too small: expected number to be >=0"
      }
    ]
  }
}
```

`issues` ist nur für `validation_error` vorhanden. Jeder Fehlerpunkt `path` auf das Feld, wobei Listenpositionen von 0 gezählt werden.

## Fehlercodes

| Status | Code                  | Was passiert                                                                                              | Was zu tun                                                                                                   |
| ------ | --------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| 400    | `validation_error`    | Ein Abfrageparameter oder Feld im Body fehlt oder ist ungültig.                                           | Beheben Sie die Felder, die in `issues` aufgelistet sind.                                                    |
| 400    | `invalid_json`        | Der Body ist kein gültiges JSON.                                                                          | Senden Sie JSON mit `Content-Type: application/json`.                                                        |
| 400    | `invalid_request`     | Die Anfrage ist gültig, aber nicht erlaubt, z. B. ein neuer Auftrag als abgeschlossen zu markieren.       | Lesen Sie `message`; nicht erneut versuchen, wenn nichts geändert wurde.                                     |
| 401    | `unauthorized`        | Fehlender, unbekannter oder widerrufener API-Schlüssel.                                                   | Prüfen Sie den `Authorization: Bearer`-Header und stellen Sie sicher, dass der Schlüssel noch aktiv ist.     |
| 401    | `key_owner_removed`   | Die Person, die den Schlüssel erstellt hat, hat den Workspace verlassen.                                  | Erstellen Sie einen neuen Schlüssel von jemandem, der noch Zugriff hat.                                      |
| 403    | `insufficient_scope`  | Ein Schreibschlüssel versuchte zu schreiben.                                                              | Verwenden Sie einen Read & write-Schlüssel.                                                                  |
| 403    | `read_only`           | API-Schreibvorgänge sind auf dem aktuellen Free-Plan des Workspaces nicht verfügbar.                      | Der Eigentümer verwaltet den Plan auf der Website. Bestehende Schlüssel können weiterhin lesen.              |
| 403    | `forbidden`           | Die Person, die den Schlüssel erstellt hat, ist nicht berechtigt, dies zu tun.                            | Fragen Sie einen Workspace-Besitzer oder erstellen Sie einen Schlüssel von jemandem mit dieser Berechtigung. |
| 403    | `workspace_suspended` | TradeCatalog hat den Workspace gesperrt. Der Eigentümer wurde per E-Mail über den Grund informiert.       | Schlüssel funktionieren wieder, sobald die Sperrung aufgehoben wird.                                         |
| 404    | `not_found`           | Keine solche Endpunkt, oder kein solches Produkt, Kunde, Auftrag oder Preisanpassung in diesem Workspace. | Prüfen Sie die ID, SKU oder Kontonummer.                                                                     |
| 405    | `method_not_allowed`  | Der Pfad existiert, aber nicht mit dieser Methode.                                                        | Verwenden Sie eine Methode aus dem `Allow`-Header.                                                           |
| 429    | `rate_limited`        | Mehr als 120 Anfragen pro Minute mit diesem Schlüssel.                                                    | Warten Sie `Retry-After` Sekunden (60), dann erneut versuchen.                                               |
| 500    | `internal_error`      | Etwas ist auf unserer Seite schiefgelaufen.                                                               | Erneut mit Backoff versuchen. Wenn es weiterhin auftritt, wenden Sie sich an den Support.                    |

IDs aus einem anderen Arbeitsbereich geben immer `404 not_found` zurück, nie Daten von jemand anderem.

## Wiederholen

Wiederholen Sie `429` und `5xx`-Antworten mit Backoff. Wiederholen Sie keine anderen `4xx`-Antworten: Sie werden auf die gleiche Weise fehlschlagen.

Alle API-Schreibvorgänge können sicher wiederholt werden: `PUT` sucht Zeilen anhand der SKU oder des Kontocodes, und `PATCH /orders/{id}` schlägt fehl mit `invalid_request`, wenn die Bestellung bereits weitergegangen ist. Daher wird bei einer Wiederholung nach einem Netzwerk-Time-out nichts dupliziert.

```js
async function api(path, init = {}, attempt = 0) {
  const res = await fetch(`https://tradecatalog.app/api/v1${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}`,
      'Content-Type': 'application/json',
      ...init.headers,
    },
  })
  if ((res.status === 429 || res.status >= 500) && attempt < 5) {
    const wait = Number(res.headers.get('Retry-After')) || 2 ** attempt
    await new Promise((resolve) => setTimeout(resolve, wait * 1000))
    return api(path, init, attempt + 1)
  }
  const body = await res.json()
  if (!res.ok) {
    const error = new Error(`${body.error.code}: ${body.error.message}`)
    error.status = res.status
    error.code = body.error.code
    error.issues = body.error.issues
    throw error
  }
  return body
}
```

## Häufige Nachrichten

| Anfrage                                               | Status und Nachricht                                                            |
| ----------------------------------------------------- | ------------------------------------------------------------------------------- |
| `GET /prices` mit einer unbekannten SKU               | `404` „Kein Produkt mit SKU HX-9999“                                            |
| Jeder Endpunkt mit einem unbekannten Kunden           | `404` „Kunde OAK99 nicht gefunden“                                              |
| `PATCH /orders/{id}` neu → abgeschlossen              | `400` „Eine empfangene Bestellung kann nicht als abgeschlossen markiert werden“ |
| `PATCH /orders/{id}` auf storniert mit keinem Hinweis | `400` „Geben Sie einen Grund für die Stornierung an“                            |
| `PUT /products` mit der gleichen SKU zweimal          | `400` Validierungsfehler „Doppelte SKU hx-8510“                                 |
