# 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
