Referenz
Konventionen & Fehler
Die Regeln, die für jeden Endpoint gelten; du musst sie nur einmal lernen.
Pagination
Listen-Endpoints nehmen page (1-basiert) und pageSize (1–100, Standard 30) als Query-Parameter und verpacken Ergebnisse in einem einheitlichen Envelope:
{
"items": [ … ],
"pageNumber": 2,
"totalPages": 9,
"totalCount": 174,
"hasPreviousPage": true,
"hasNextPage": true
}Enums sind camelCase-Strings
Enum-Werte sind immer Strings in camelCase, niemals Integer: "pounds", "kilometers", "oneRepMax", "chest", "normal". Behandle unbekannte Enum-Werte als vorwärtskompatibel: neue können ohne Versionssprung auftauchen.
Einheiten
| Messgröße | Einheit |
|---|---|
| Gewicht (Sätze, Rekorde) | Pfund |
| Distanz | Meter |
| Satz-/Rekord-Dauer | Sekunden |
| Workout-Dauer | Minuten (durationMinutes) |
| Körpermessungen | Das Einheitensystem aus dem weightUnit des Eintrags (Inches bei Pfund, Zentimeter bei Kilogramm) |
Die bevorzugten Anzeigeeinheiten des Nutzers stehen auf /api/v1/user. Konvertiere am Rand deiner App, nicht in der Datenhaltung.
Identifikatoren
- Nutzerdaten (Workouts, Vorlagen, Splits, Messungen): stabile GUIDs
- Katalogdaten (Übungen, Equipment): stabile Integer-IDs, dieselben wie in der Gravl-App
- Der Nutzer: eine opake String-ID, stabil über alle Endpoints und Tokens hinweg
Datumsangaben
Alle Zeitstempel sind UTC, ISO 8601 (2026-07-12T17:03:00Z). Datumsbereichsfilter (startDate, endDate) sind inklusiv.
Rate Limits
| Bereich | Limit | Bezugsgröße |
|---|---|---|
/api/v1/* | 100 Requests / 15 Min | App + Nutzer |
/oauth/* | 10 Requests / Min | IP-Adresse |
Beim Überschreiten eines Limits kommt 429 zurück, wenn möglich mit einem Retry-After-Header. Warte exponentiell länger und verzichte auf Polling; die meisten persönlichen Daten ändern sich in menschlichem Tempo.
Fehler
| Status | Wann | Body |
|---|---|---|
| 401 | Fehlendes, fehlerhaftes, abgelaufenes oder widerrufenes Token; gesperrte App | Leer (WWW-Authenticate-Challenge) |
| 403 | Gültiges Token, fehlender Scope | Problem Details mit dem fehlenden Scope benannt |
| 404 | Ressource existiert nicht oder gehört einem anderen Nutzer | Problem Details |
| 429 | Rate Limit erreicht | Leer; Retry-After-Header |
| 400 | Validierungsfehler (falsche Seitengröße, fehlerhafte Parameter) | Problem Details mit Feld-Fehlern |
{
"status": 403,
"title": "Missing scope",
"detail": "This authorization is missing the 'measurements:read' scope."
}Beachte die 404-Regel für fremde Daten: das Anfragen des Workouts eines anderen Nutzers per ID gibt 404 zurück, nicht 403. Die API bestätigt niemals, dass Daten existieren, die du nicht sehen darfst.