Zwei Formen, immer gleich.
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.
curl -s https://app.upfour.io/v1/monitors/$MONITOR_ID \
-H "Authorization: Bearer $UP4_API_KEY"{ "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
dataodererrorauf oberster Ebene, bleibt sie unverändert. 204 No Contenthat keinen Body. Dateien wie Berichtsexporte sind kein JSON und werden nicht verpackt.- In einer Antwort können neue Felder auftauchen; das Änderungsprotokoll (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.
{
"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 (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 | Die Anfrage ist fehlerhaft oder ein Feld ist ungültig. Ein Feldfehler bringt details.field mit. |
| 401 | unauthorized | Kein gültiger Schlüssel. Siehe API-Schlüssel und Scopes. |
| 402 | payment_required | Tarif oder Abrechnungsstand des Unternehmens erlauben die Aktion nicht. |
| 403 | permission_denied | Abgewiesen. Scope-Fehler haben eigene Codes, siehe API-Schlüssel und Scopes. |
| 404 | not_found | Die Ressource gibt es nicht, oder dein Schlüssel darf sie nicht sehen. |
| 409 | conflict | Die Anfrage kollidiert mit dem aktuellen Stand. Idempotenz-Konflikte haben eigene Codes. |
| 429 | rate_limit_exceeded | Zu viele Anfragen. Warte die Zeit aus Retry-After ab. |
| 503 | 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 | 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.
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.messageprüfen. Prüfeerror.codeund den Status. datain einer Fehlerantwort lesen. Dort gibt es keins.- Einen Body bei
204erwarten. - Jedes
403fü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 ohneIdempotency-Keywiederholen. Mit Schlüssel bekommst du die gespeicherte Antwort zurück, wenn die erste Anfrage unter 500 geendet hat; ein5xxselbst wird nicht gespeichert. Siehe Idempotenz.
War diese Seite hilfreich?