mitai-jinkendo/.claude/docs/technical/API_REFERENCE.md
Lars 7940dc7560 docs: Struktur .claude/docs versionieren, working/, Gitea-Index, Regeln
- .gitignore: .claude/docs, rules, commands tracken; settings.local weiter ignorieren
- DOCUMENTATION.md: verbindliche Ablage functional/technical/working/issues
- .claude/README.md: Agent-Einstieg; GITEA_ISSUES_INDEX aus MCP (Stand 2026-04-08)
- Arbeitspapiere von docs/ nach .claude/docs/working/ verschoben
- docs/MEMBERSHIP_SYSTEM.md als Stub; kanonisch technical/MEMBERSHIP_SYSTEM.md
- CLAUDE.md Pflichtlektüre und Links angepasst; docs/README.md vereinfacht

Made-with: Cursor
2026-04-08 13:01:49 +02:00

576 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API-Referenz
## Basis-URLs
| Umgebung | URL |
|----------|-----|
| **Production** | `https://mitai.jinkendo.de/api` |
| **Development** | `https://dev.mitai.jinkendo.de/api` |
| **Local** | `http://localhost:8000/api` (Backend direkt) |
---
## Authentifizierung
**Alle geschützten Endpoints** benötigen einen Auth-Token im Header:
```http
GET /api/weight
X-Auth-Token: jT9z3xK...pQ2vL
```
**Token-Beschaffung:** `POST /api/auth/login``{"token": "..."}`
**Storage:** `localStorage.bodytrack_token` (Frontend)
---
## Fehler-Codes
| Status | Bedeutung | Beispiel |
|--------|-----------|----------|
| **200** | Erfolg | `{"data": [...]}` |
| **201** | Erstellt | `{"id": "uuid", ...}` |
| **400** | Bad Request | `{"detail": "Ungültige Eingabe"}` |
| **401** | Unauthorized | `{"detail": "Nicht eingeloggt"}` |
| **403** | Forbidden | `{"detail": "Nur für Admins"}` oder `{"detail": "Feature-Limit erreicht"}` |
| **404** | Not Found | `{"detail": "Eintrag nicht gefunden"}` |
| **429** | Too Many Requests | `{"detail": "Rate limit exceeded: 5 per 1 minute"}` |
| **500** | Server Error | `{"detail": "Interner Fehler"}` |
**Standard-Fehler-Format:**
```json
{
"detail": "Fehlermeldung"
}
```
---
## Rate Limits
| Endpoint | Limit | Grund |
|----------|-------|-------|
| `POST /api/auth/login` | 5/minute | Brute-Force-Schutz |
| `POST /api/auth/register` | 3/hour | Spam-Prevention |
| `POST /api/auth/forgot-password` | 3/minute | E-Mail-Flooding-Schutz |
| `POST /api/auth/resend-verification` | 3/hour | E-Mail-Flooding-Schutz |
**Andere Endpoints:** Keine Rate-Limits (Feature-Limits via Membership-System)
---
## Endpoints nach Modul
### 1. Auth (`/api/auth/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `POST` | `/auth/login` | ❌ | `{email, password}` | `{token, profile_id, name, role, expires_at}` | Login mit E-Mail + Passwort |
| `POST` | `/auth/logout` | ✅ | | `{ok: true}` | Logout (löscht Session) |
| `GET` | `/auth/me` | ✅ | | `{id, name, email, role, tier, ...}` | Aktuelles Profil abrufen |
| `GET` | `/auth/status` | ❌ | | `{status: "ok", version: "v9b"}` | Health Check |
| `PUT` | `/auth/pin` | ✅ | `{pin}` | `{ok: true}` | PIN/Passwort ändern |
| `POST` | `/auth/forgot-password` | ❌ | `{email}` | `{ok: true, message}` | Passwort-Reset anfordern |
| `POST` | `/auth/reset-password` | ❌ | `{token, new_password}` | `{ok: true, message}` | Passwort-Reset bestätigen |
| `POST` | `/auth/register` | ❌ | `{name, email, password}` | `{ok: true, message}` | Selbst-Registrierung |
| `GET` | `/auth/verify/{token}` | ❌ | | `{ok: true, token, profile}` | E-Mail-Verifizierung |
| `POST` | `/auth/resend-verification` | ❌ | `{email}` | `{ok: true, message}` | Verifizierungs-E-Mail erneut senden |
**Rate Limits:** Siehe Tabelle oben
---
### 2. Profiles (`/api/profiles/*`, `/api/profile`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/profile` | ✅ | | `{id, name, email, role, tier, ...}` | Aktives Profil |
| `PUT` | `/profile` | ✅ | `{name?, sex?, dob?, height?, goal_weight?, goal_bf_pct?, avatar_color?}` | `{ok: true}` | Profil aktualisieren |
| `GET` | `/profiles` | ✅ | | `[{id, name, ...}, ...]` | Alle Profile (Multi-User, derzeit nicht genutzt) |
| `POST` | `/profiles` | ✅ | `{name, ...}` | `{id, ...}` | Profil erstellen (Multi-User) |
| `PUT` | `/profiles/{id}` | ✅ | `{name?, ...}` | `{ok: true}` | Profil bearbeiten |
| `DELETE` | `/profiles/{id}` | ✅ | | `{ok: true}` | Profil löschen |
---
### 3. Weight (`/api/weight/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/weight` | ✅ | `?limit=365` | `[{id, date, weight, note, source, created}, ...]` | Gewichtseinträge abrufen |
| `POST` | `/weight` | ✅ | `{date, weight, note?}` | `{id, date, weight, ...}` | Gewicht eintragen (Upsert) |
| `PUT` | `/weight/{id}` | ✅ | `{date, weight, note?}` | `{ok: true}` | Eintrag bearbeiten |
| `DELETE` | `/weight/{id}` | ✅ | | `{ok: true}` | Eintrag löschen |
| `GET` | `/weight/stats` | ✅ | | `{latest, avg_7d, avg_30d, delta_7d, delta_30d, trend}` | Gewichts-Statistiken |
**Feature-Limits:** `weight_entries` (v9c Phase 4: Enforcement aktiv)
---
### 4. Circumferences (`/api/circumferences/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/circumferences` | ✅ | `?limit=100` | `[{id, date, c_neck, c_chest, c_waist, c_belly, c_hip, c_thigh, c_calf, c_arm, notes, photo_id}, ...]` | Umfangsmessungen |
| `POST` | `/circumferences` | ✅ | `{date, c_neck?, c_chest?, ...}` | `{id, ...}` | Messung eintragen (Upsert) |
| `PUT` | `/circumferences/{id}` | ✅ | `{date, ...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/circumferences/{id}` | ✅ | | `{ok: true}` | Löschen |
**Feature-Limits:** `circumference_entries`
---
### 5. Caliper (`/api/caliper/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/caliper` | ✅ | `?limit=100` | `[{id, date, sf_method, sf_chest, sf_abdomen, ..., body_fat_pct, lean_mass, fat_mass, notes}, ...]` | Hautfaltenmessungen |
| `POST` | `/caliper` | ✅ | `{date, sf_method, sf_chest?, ...}` | `{id, body_fat_pct, ...}` | Messung eintragen (berechnet KF% automatisch) |
| `PUT` | `/caliper/{id}` | ✅ | `{date, ...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/caliper/{id}` | ✅ | | `{ok: true}` | Löschen |
**Methoden:** `jackson3`, `jackson7`, `durnin`, `parrillo`
**Feature-Limits:** `caliper_entries`
---
### 6. Activity (`/api/activity/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/activity` | ✅ | `?limit=200` | `[{id, date, start_time, end_time, activity_type, duration_min, kcal_active, hr_avg, hr_max, distance_km, rpe, source, notes}, ...]` | Aktivitäten |
| `POST` | `/activity` | ✅ | `{date, activity_type, duration_min, ...}` | `{id, ...}` | Aktivität erstellen |
| `PUT` | `/activity/{id}` | ✅ | `{date, ...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/activity/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/activity/stats` | ✅ | | `{total_activities, total_kcal, avg_duration, ...}` | Statistiken |
| `GET` | `/activity/uncategorized` | ✅ | | `[{activity_type, count}, ...]` | Unkategorisierte Aktivitäten |
| `POST` | `/activity/bulk-categorize` | ✅ | `[{activity_type, training_type_id}, ...]` | `{ok: true, updated_count}` | Bulk-Kategorisierung (lernendes System) |
| `POST` | `/activity/import-csv` | ✅ | `FormData(file)` | `{imported, skipped, failed, errors}` | Apple Health CSV-Import |
**Feature-Limits:** `activity_entries`
---
### 7. Nutrition (`/api/nutrition/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/nutrition` | ✅ | `?limit=365` | `[{id, date, kcal, protein_g, fat_g, carbs_g, source}, ...]` | Ernährungsdaten |
| `GET` | `/nutrition/by-date/{date}` | ✅ | | `{id, date, kcal, ...}` oder `null` | Eintrag für bestimmtes Datum |
| `POST` | `/nutrition` | ✅ | `?date=YYYY-MM-DD&kcal=2000&protein_g=150&fat_g=70&carbs_g=200` | `{id, ...}` | Eintrag erstellen (Upsert) |
| `PUT` | `/nutrition/{id}` | ✅ | `?kcal=2000&...` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/nutrition/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/nutrition/correlations` | ✅ | | `{weight_vs_kcal: [...], bf_vs_protein: [...]}` | Korrelationen |
| `GET` | `/nutrition/weekly` | ✅ | `?weeks=16` | `[{week, year, avg_kcal, avg_protein, ...}, ...]` | Wochendaten |
| `GET` | `/nutrition/import-history` | ✅ | | `[{date, count}, ...]` | Import-Historie |
| `POST` | `/nutrition/import-csv` | ✅ | `FormData(file)` | `{imported, skipped, failed, errors}` | CSV-Import (FDDB, MyFitnessPal) |
**Feature-Limits:** `nutrition_entries`, `data_import`
---
### 8. Photos (`/api/photos/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/photos` | ✅ | | `[{id, date, path, created}, ...]` | Alle Fotos |
| `GET` | `/photos/{id}` | ✅ | `?token=...` (optional) | Binary (JPEG) | Foto abrufen (Token für <img> tag) |
| `POST` | `/photos` | ✅ | `FormData(file, date?)` | `{id, path, date}` | Foto hochladen |
| `DELETE` | `/photos/{id}` | ✅ | | `{ok: true}` | Foto löschen |
**Feature-Limits:** `photos`
**Hinweis:** Token-Parameter für `GET /photos/{id}` erlaubt Zugriff via `<img>` tag (ohne Header-Support)
---
### 9. AI Insights (`/api/insights/*`, `/api/ai/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/insights` | ✅ | | `[{id, scope, content, created}, ...]` | Alle Insights |
| `GET` | `/insights/latest` | ✅ | | `{slug: content, ...}` | Neueste Insights pro Scope |
| `POST` | `/insights/trend` | ✅ | | `{content, usage}` | Trend-Analyse (Gewicht) |
| `POST` | `/insights/run/{slug}` | ✅ | | `{content, usage}` | Einzelnen Prompt ausführen |
| `POST` | `/insights/pipeline` | ✅ | | `{content, usage}` | 3-stufige Pipeline |
**Feature-Limits:** `ai_calls` (pro Aufruf), `ai_pipeline` (für Pipeline)
**Prompts:** Konfigurierbar via `/api/prompts`
---
### 10. AI Prompts (`/api/prompts/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/prompts` | ✅ | | `[{id, slug, name, description, template, active, sort_order}, ...]` | Alle Prompts |
| `PUT` | `/prompts/{id}` | 🔒 Admin | `{name?, description?, template?, active?, sort_order?}` | `{ok: true}` | Prompt bearbeiten |
**Standard-Prompts:**
- `weight-trend` Gewichts-Trend-Analyse
- `nutrition-analysis` Ernährungs-Auswertung
- `training-plan` Trainings-Empfehlungen
- `body-composition` Körperzusammensetzung
- `progress-summary` Fortschritts-Zusammenfassung
- `pipeline` Master-Schalter für Pipeline
---
### 11. Admin (`/api/admin/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/admin/profiles` | 🔒 Admin | | `[{id, name, email, role, tier, ...}, ...]` | Alle Profile |
| `POST` | `/admin/profiles` | 🔒 Admin | `{name, email, password, role?}` | `{id, ...}` | Profil erstellen |
| `DELETE` | `/admin/profiles/{id}` | 🔒 Admin | | `{ok: true}` | Profil löschen |
| `PUT` | `/admin/profiles/{id}/permissions` | 🔒 Admin | `{ai_enabled?, ai_limit_day?, export_enabled?}` | `{ok: true}` | Permissions setzen |
---
### 12. Stats (`/api/stats`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/stats` | ✅ | | `{weight: {...}, nutrition: {...}, activity: {...}, body_comp: {...}}` | Dashboard-Stats |
**Response-Struktur:**
```json
{
"weight": {
"latest": 75.5,
"avg_7d": 75.8,
"avg_30d": 76.2,
"delta_7d": -0.3,
"delta_30d": -0.7
},
"nutrition": {
"avg_kcal_7d": 2100,
"avg_protein_7d": 150,
"days_logged_7d": 6
},
"activity": {
"total_activities_7d": 5,
"total_kcal_7d": 2500,
"avg_duration_7d": 45
},
"body_comp": {
"latest_bf_pct": 12.5,
"latest_lean_mass": 65.8
}
}
```
---
### 13. Export (`/api/export/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/export/csv` | ✅ | | Binary (CSV) | Alle Daten als CSV |
| `GET` | `/export/json` | ✅ | | Binary (JSON) | Alle Daten als JSON |
| `GET` | `/export/zip` | ✅ | | Binary (ZIP) | Alle Daten + Fotos als ZIP |
**Feature-Limits:** `data_export`
**Dateiname:** `mitai-export-YYYY-MM-DD.[csv|json|zip]`
**ZIP-Struktur:**
```
mitai-export-2026-03-23.zip
├── data.json
├── photos/
│ ├── photo_uuid1.jpg
│ └── photo_uuid2.jpg
└── README.txt
```
---
### 14. Import (`/api/import/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `POST` | `/import/backup` | ✅ | `FormData(file)` | `{imported: {...}, skipped: {...}, failed: {...}}` | JSON-Backup importieren |
**Feature-Limits:** `data_import`
**Format:** JSON-Export von `/export/json`
**Hinweis:** Überschreibt keine existierenden Einträge (Upsert-Logik)
---
## Subscription System (v9c)
### 15. Subscription (`/api/subscription/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/subscription/me` | ✅ | | `{tier, tier_expires_at, trial_ends_at, invited_by, ...}` | Abo-Status |
| `GET` | `/subscription/usage` | ✅ | | `{feature_id: {used, limit, remaining, allowed}, ...}` | Feature-Usage |
| `GET` | `/subscription/limits` | ✅ | | `{feature_id: limit, ...}` | Feature-Limits für aktuelles Tier |
---
### 16. Coupons (`/api/coupons/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `POST` | `/coupons/redeem` | ✅ | `{code}` | `{ok: true, tier_id, valid_days, message}` | Coupon einlösen |
| `GET` | `/coupons` | 🔒 Admin | | `[{id, code, tier_id, valid_days, max_uses, ...}, ...]` | Alle Coupons |
| `POST` | `/coupons` | 🔒 Admin | `{code, tier_id, valid_days, max_uses?}` | `{id, ...}` | Coupon erstellen |
| `PUT` | `/coupons/{id}` | 🔒 Admin | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/coupons/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
| `GET` | `/coupons/{id}/redemptions` | 🔒 Admin | | `[{profile_id, redeemed_at}, ...]` | Einlösungen |
---
### 17. Features (`/api/features/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/features` | ✅ | | `[{id, name, description, limit_type, reset_period, default_limit, active}, ...]` | Alle Features |
| `GET` | `/features/usage` | ✅ | | `[{feature_id, feature_name, limit, used, remaining, allowed, reason}, ...]` | Feature-Usage für aktuellen User |
| `POST` | `/features` | 🔒 Admin | `{id, name, description, limit_type, reset_period, default_limit}` | `{id, ...}` | Feature erstellen |
| `PUT` | `/features/{id}` | 🔒 Admin | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/features/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
**Limit-Types:** `count` (zählbar), `boolean` (on/off)
**Reset-Periods:** `never`, `daily`, `monthly`
---
### 18. Tiers (`/api/tiers/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/tiers` | 🔒 Admin | | `[{id, name, description, price_monthly, active}, ...]` | Alle Tiers |
| `POST` | `/tiers` | 🔒 Admin | `{id, name, description, price_monthly}` | `{id, ...}` | Tier erstellen |
| `PUT` | `/tiers/{id}` | 🔒 Admin | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/tiers/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
**Standard-Tiers:** `free`, `basic`, `premium`, `selfhosted`
---
### 19. Tier Limits (`/api/tier-limits/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/tier-limits` | 🔒 Admin | | `{tiers: [...], features: [...], matrix: {...}}` | Tier-Limits-Matrix |
| `PUT` | `/tier-limits` | 🔒 Admin | `{tier_id, feature_id, limit_value}` | `{ok: true}` | Limit setzen |
| `PUT` | `/tier-limits/batch` | 🔒 Admin | `{updates: [{tier_id, feature_id, limit_value}, ...]}` | `{ok: true}` | Batch-Update |
**Matrix-Format:**
```json
{
"tiers": ["free", "basic", "premium", "selfhosted"],
"features": [
{"id": "weight_entries", "name": "Gewichtseinträge", ...},
...
],
"matrix": {
"weight_entries": {
"free": 100,
"basic": 1000,
"premium": null,
"selfhosted": null
},
...
}
}
```
---
### 20. User Restrictions (`/api/user-restrictions/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/user-restrictions` | 🔒 Admin | `?profile_id=...` | `[{id, profile_id, feature_id, limit_value}, ...]` | User-spezifische Limits |
| `POST` | `/user-restrictions` | 🔒 Admin | `{profile_id, feature_id, limit_value}` | `{id, ...}` | Limit setzen |
| `PUT` | `/user-restrictions/{id}` | 🔒 Admin | `{limit_value}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/user-restrictions/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
**Verwendung:** Individuelle Limits überschreiben Tier-Limits
---
### 21. Access Grants (`/api/access-grants/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/access-grants` | 🔒 Admin | `?profile_id=...&active_only=true` | `[{id, profile_id, tier_id, valid_from, valid_until, source, is_active}, ...]` | Zeitlich begrenzte Tier-Zugriffe |
| `POST` | `/access-grants` | 🔒 Admin | `{profile_id, tier_id, valid_from, valid_until, source?}` | `{id, ...}` | Grant erstellen |
| `PUT` | `/access-grants/{id}` | 🔒 Admin | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/access-grants/{id}` | 🔒 Admin | | `{ok: true}` | Revoke |
**Quellen:** `coupon`, `trial`, `manual`, `gift`
---
## Training Types (v9d)
### 22. Training Types (`/api/training-types/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/training-types` | ✅ | | `{category: [{id, name, category, color, icon}, ...], ...}` | Gruppiert nach Kategorie |
| `GET` | `/training-types/flat` | ✅ | | `[{id, name, category, ...}, ...]` | Flache Liste |
| `GET` | `/training-types/categories` | ✅ | | `[{id, name, icon, color}, ...]` | Kategorien-Metadaten |
**Kategorien:** Kraft, Cardio, Flexibilität, Spiel & Sport, Alltag & Bewegung, Outdoor & Natur, Geist & Meditation
---
### 23. Admin Training Types (`/api/admin/training-types/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/admin/training-types` | 🔒 Admin | | `[{id, name, category, color, icon, abilities}, ...]` | Alle Typen (inkl. abilities JSONB) |
| `GET` | `/admin/training-types/{id}` | 🔒 Admin | | `{id, name, ...}` | Einzelner Typ |
| `POST` | `/admin/training-types` | 🔒 Admin | `{name, category, color?, icon?}` | `{id, ...}` | Typ erstellen |
| `PUT` | `/admin/training-types/{id}` | 🔒 Admin | `{name?, category?, color?, icon?, abilities?}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/admin/training-types/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
| `GET` | `/admin/training-types/taxonomy/abilities` | 🔒 Admin | | `{categories: [...], abilities: [...]}` | Abilities-Taxonomie (v9f) |
---
### 24. Activity Mappings (`/api/admin/activity-mappings/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/admin/activity-mappings` | 🔒 Admin | `?profile_id=...&global_only=true` | `[{id, activity_type, training_type_id, profile_id, is_global}, ...]` | Lernendes Mapping-System |
| `GET` | `/admin/activity-mappings/{id}` | 🔒 Admin | | `{id, ...}` | Einzelnes Mapping |
| `POST` | `/admin/activity-mappings` | 🔒 Admin | `{activity_type, training_type_id, profile_id?, is_global?}` | `{id, ...}` | Mapping erstellen |
| `PUT` | `/admin/activity-mappings/{id}` | 🔒 Admin | `{training_type_id?, is_global?}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/admin/activity-mappings/{id}` | 🔒 Admin | | `{ok: true}` | Löschen |
| `GET` | `/admin/activity-mappings/stats/coverage` | 🔒 Admin | | `{total_activities, mapped, unmapped, coverage_pct}` | Mapping-Coverage |
**Auto-Learning:** Bulk-Kategorisierung in ActivityPage speichert neue Mappings automatisch
---
### 25. Training Profiles (`/api/evaluation/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/evaluation/parameters` | 🔒 Admin | | `{categories: [...], abilities: [...]}` | Training-Parameter-Taxonomie |
| `POST` | `/evaluation/batch` | 🔒 Admin | | `{evaluated, failed, errors}` | Batch-Evaluierung aller Aktivitäten (v9d #15) |
---
## Sleep & Vitals (v9d Phase 2)
### 26. Sleep (`/api/sleep/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/sleep` | ✅ | `?limit=90` | `[{id, date, bedtime, wakeup, duration_min, quality, sleep_segments, notes, source}, ...]` | Schlaf-Einträge |
| `GET` | `/sleep/by-date/{date}` | ✅ | | `{id, date, ...}` oder `null` | Eintrag für Datum |
| `POST` | `/sleep` | ✅ | `{date, bedtime, wakeup, duration_min, quality?, sleep_segments?, notes?}` | `{id, ...}` | Eintrag erstellen (Upsert) |
| `PUT` | `/sleep/{id}` | ✅ | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/sleep/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/sleep/stats` | ✅ | `?days=7` | `{avg_duration, avg_quality, total_deep, total_rem, ...}` | Stats |
| `GET` | `/sleep/debt` | ✅ | `?days=14` | `{sleep_debt_min, avg_duration, target_duration}` | Schlafschuld |
| `GET` | `/sleep/trend` | ✅ | `?days=30` | `[{date, duration_min, quality}, ...]` | Trend |
| `GET` | `/sleep/phases` | ✅ | `?days=30` | `[{date, deep_min, rem_min, light_min, awake_min}, ...]` | Schlafphasen |
| `POST` | `/sleep/import/apple-health` | ✅ | `FormData(file)` | `{imported, skipped, failed, errors}` | Apple Health CSV-Import |
**sleep_segments Format (JSONB):**
```json
[
{"phase": "deep", "start": "23:30", "end": "01:15"},
{"phase": "rem", "start": "01:15", "end": "02:45"},
{"phase": "light", "start": "02:45", "end": "06:00"},
{"phase": "awake", "start": "06:00", "end": "06:15"}
]
```
---
### 27. Rest Days (`/api/rest-days/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/rest-days` | ✅ | `?limit=90` | `[{id, date, rest_type, reason, notes}, ...]` | Ruhetage |
| `GET` | `/rest-days/{id}` | ✅ | | `{id, ...}` | Einzelner Eintrag |
| `POST` | `/rest-days` | ✅ | `{date, rest_type, reason?, notes?}` | `{id, ...}` | Ruhetag eintragen |
| `PUT` | `/rest-days/{id}` | ✅ | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/rest-days/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/rest-days/stats` | ✅ | `?weeks=4` | `{total_rest_days, kraft_days, cardio_days, entspannung_days}` | Stats |
| `POST` | `/rest-days/validate-activity` | ✅ | `{date, activity_type}` | `{conflicts: [{rest_type, reason}, ...]}` | Validierung gegen Ruhetage |
**rest_type:** `kraft`, `cardio`, `entspannung` (Multi-Dimensional Rest)
---
### 28. Vitals Baseline (`/api/vitals/baseline/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/vitals/baseline` | ✅ | `?limit=90` | `[{id, date, resting_hr, hrv, vo2_max, spo2, respiratory_rate, notes}, ...]` | Morgenmessungen |
| `GET` | `/vitals/baseline/by-date/{date}` | ✅ | | `{id, ...}` oder `null` | Eintrag für Datum |
| `POST` | `/vitals/baseline` | ✅ | `{date, resting_hr?, hrv?, vo2_max?, spo2?, respiratory_rate?, notes?}` | `{id, ...}` | Eintrag erstellen (Upsert) |
| `PUT` | `/vitals/baseline/{id}` | ✅ | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/vitals/baseline/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/vitals/baseline/stats` | ✅ | `?days=30` | `{avg_resting_hr, avg_hrv, trend_resting_hr, trend_hrv}` | Stats |
| `POST` | `/vitals/baseline/import/apple-health` | ✅ | `FormData(file)` | `{imported, skipped, failed, errors}` | Apple Health CSV-Import |
**Messung:** 1x täglich, morgens nüchtern
---
### 29. Blood Pressure (`/api/blood-pressure/*`)
| Methode | Pfad | Auth | Parameter | Response | Beschreibung |
|---------|------|------|-----------|----------|--------------|
| `GET` | `/blood-pressure` | ✅ | `?limit=90` | `[{id, date, time, systolic, diastolic, pulse, context, irregular_heartbeat, afib_warning, notes}, ...]` | Blutdruck-Messungen |
| `GET` | `/blood-pressure/by-date/{date}` | ✅ | | `[{id, time, ...}, ...]` | Alle Messungen für Datum |
| `POST` | `/blood-pressure` | ✅ | `{date, time, systolic, diastolic, pulse?, context?, irregular_heartbeat?, afib_warning?, notes?}` | `{id, ...}` | Messung eintragen |
| `PUT` | `/blood-pressure/{id}` | ✅ | `{...}` | `{ok: true}` | Bearbeiten |
| `DELETE` | `/blood-pressure/{id}` | ✅ | | `{ok: true}` | Löschen |
| `GET` | `/blood-pressure/stats` | ✅ | `?days=30` | `{avg_systolic, avg_diastolic, avg_pulse, classification, trend}` | Stats |
| `POST` | `/blood-pressure/import/omron` | ✅ | `FormData(file)` | `{imported, skipped, failed, errors}` | Omron CSV-Import (Deutsch) |
**Contexts:** `fasting`, `after_meal`, `exercise`, `stress`, `rest`, `before_sleep`, `after_sleep`, `medication`
**WHO/ISH-Klassifizierung:**
- Optimal: <120/<80
- Normal: 120-129/80-84
- Hoch-Normal: 130-139/85-89
- Hypertonie Grad 1: 140-159/90-99
- Hypertonie Grad 2: 160-179/100-109
- Hypertonie Grad 3: 180/≥110
---
## Zusammenfassung
**Gesamt:** 29 Router-Module, ~200 Endpoints
**Authentifizierung:** Token-basiert (X-Auth-Token Header)
**Fehlerformat:** `{"detail": "Fehlermeldung"}`
**Rate Limits:** Nur Auth-Endpoints (5/min Login, 3/hour Register)
**Feature-Limits:** Membership-basiert (v9c), enforcement via HTTP 403
**Import-Formate:** CSV (Apple Health, Omron, FDDB), JSON (Backup)
**Export-Formate:** CSV, JSON, ZIP (mit Fotos)
**Besonderheiten:**
- Upsert-Logik für viele Endpoints (Date-basiert)
- Inline-Editing-Support (GET by date, PUT by id)
- CSV-Import mit Duplikat-Erkennung
- Lernendes Mapping-System (Activity Types)
- JSONB für flexible Datenstrukturen (sleep_segments, abilities)
- Auto-Migration SHA256 bcrypt
- E-Mail-Verifizierung + Passwort-Reset