# Antworten und Fehler

> Die zwei Antwortformen der up4-API: der data-Umschlag bei Erfolg und das error-Objekt bei einem Fehler, mit den Standardcodes je Status und der Request-ID für den Support.

Source: https://upfour.io/de/docs/api/responses

Ein erfolgreicher Aufruf liefert `data`. Ein fehlgeschlagener liefert `error`. Du erkennst den Unterschied am Statuscode und am einen Schlüssel ganz oben.

## Erfolg

Eine 2xx-Antwort mit JSON-Body verpackt ihren Inhalt als `{ "data": … }`. Eine Liste legt ein Array in `data` und ergänzt `pagination`; was dieses Objekt bedeutet, hängt vom Endpunkt ab, siehe [Paginierung](https://upfour.io/de/docs/api/pagination.md).

```bash
curl -s https://app.upfour.io/v1/monitors/$MONITOR_ID \
  -H "Authorization: Bearer $UP4_API_KEY"
```

```json
{ "data": { "id": "…", "name": "Example", … } }

{
  "data": [ … ],
  "pagination": {
    "cursor": null,
    "next_cursor": null,
    "prev_cursor": null,
    "limit": 50,
    "has_more": false
  }
}
```

- Der Umschlag gilt für jeden Aufruf mit einem API-Schlüssel. Enthält eine Antwort schon ein `data` oder `error` auf oberster Ebene, bleibt sie unverändert.
- `204 No Content` hat keinen Body. Dateien wie Berichtsexporte sind kein JSON und werden nicht verpackt.
- In einer Antwort können neue Felder auftauchen; das [Änderungsprotokoll](https://upfour.io/docs/api/changelog.md) (englisch) führt sie als „added“. Ignoriere Felder, die du nicht kennst.

## Fehler

Jede 4xx- und 5xx-Antwort nutzt ein Objekt, mit `Content-Type: application/json`. Fehler stecken nicht in `data`.

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "API token does not have the required scope",
    "request_id": "req_…",
    "details": { "required_scope": "monitor.write" }
  }
}
```

| Feld | Bedeutung |
| --- | --- |
| `error.code` | Eine stabile Kennung in snake_case. Verzweige danach. |
| `error.message` | Ein Satz für Menschen. Er kann sich ändern; vergleiche nicht damit. |
| `error.request_id` | Die Kennung dieser Anfrage, identisch mit dem Antwort-Header `X-Request-Id`. |
| `error.details` | Nur vorhanden, wenn es mehr zu sagen gibt: `field` nennt das ungültige Feld, `required_scope` den fehlenden Scope, `original_request_at` die erste Verwendung eines Idempotenz-Schlüssels. |

Jeden Code mit Status und Ursache findest du im [Fehlerkatalog](https://upfour.io/docs/api/errors.md) (englisch).

## Statuscodes

Ein Status ohne spezielleren Code bekommt den Standardcode aus der Tabelle. Viele Fehler tragen stattdessen einen eigenen Code, etwa `cursor_expired` oder `idempotency_key_conflict`.

| Status | Standard-error.code | Bedeutet meistens |
| --- | --- | --- |
| 400 | [bad_request](https://upfour.io/docs/api/errors#code-bad_request) | Die Anfrage ist fehlerhaft oder ein Feld ist ungültig. Ein Feldfehler bringt details.field mit. |
| 401 | [unauthorized](https://upfour.io/docs/api/errors#code-unauthorized) | Kein gültiger Schlüssel. Siehe API-Schlüssel und Scopes. |
| 402 | [payment_required](https://upfour.io/docs/api/errors#code-payment_required) | Tarif oder Abrechnungsstand des Unternehmens erlauben die Aktion nicht. |
| 403 | [permission_denied](https://upfour.io/docs/api/errors#code-permission_denied) | Abgewiesen. Scope-Fehler haben eigene Codes, siehe API-Schlüssel und Scopes. |
| 404 | [not_found](https://upfour.io/docs/api/errors#code-not_found) | Die Ressource gibt es nicht, oder dein Schlüssel darf sie nicht sehen. |
| 409 | [conflict](https://upfour.io/docs/api/errors#code-conflict) | Die Anfrage kollidiert mit dem aktuellen Stand. Idempotenz-Konflikte haben eigene Codes. |
| 429 | [rate_limit_exceeded](https://upfour.io/docs/api/errors#code-rate_limit_exceeded) | Zu viele Anfragen. Warte die Zeit aus Retry-After ab. |
| 503 | [service_unavailable](https://upfour.io/docs/api/errors#code-service_unavailable) | Ein bewusster Hinweis, zum Beispiel für eine Funktion, die gerade nicht verfügbar ist. Die Meldung ist zum Lesen gedacht. |
| sonstige 5xx | [internal_error](https://upfour.io/docs/api/errors#code-internal_error) | Unser Fehler. Die Meldung lautet immer „Internal server error“; schick uns die request_id. |

Jeder andere Status fällt auf `request_failed` zurück.

## Request-IDs

Jede Antwort, ob Erfolg oder Fehler, trägt `X-Request-Id`. Sendest du den Header mit, übernimmt up4 deinen Wert; sonst erzeugt up4 `req_` gefolgt von einer UUID. Schreib sie ins Log und nenne sie dem Support.

```bash
curl -si https://app.upfour.io/v1/me \
  -H "Authorization: Bearer $UP4_API_KEY" \
  -H "X-Request-Id: nightly-sync-2026-10-27" | grep -i '^x-request-id'
```

## Typische Fehler

- Auf `error.message` prüfen. Prüfe `error.code` und den Status.
- `data` in einer Fehlerantwort lesen. Dort gibt es keins.
- Einen Body bei `204` erwarten.
- Jedes `403` für endgültig halten. Einen fehlenden Scope oder einen Schlüssel zum Lesen behebt ein neuer Schlüssel.
- Ein `5xx`\-POST oder einen POST ohne Antwort ohne `Idempotency-Key` wiederholen. Mit Schlüssel bekommst du die gespeicherte Antwort zurück, wenn die erste Anfrage unter 500 geendet hat; ein `5xx` selbst wird nicht gespeichert. Siehe [Idempotenz](https://upfour.io/de/docs/api/idempotency.md).
