281 lines
8.6 KiB
Markdown
281 lines
8.6 KiB
Markdown
# API-Vertrag boehmitools Training
|
|
|
|
Stand: aus dem vollständigen boehmitools-Quellstand und den Plugins `trainingsplan`/`trainingstracker` 2.0 abgeleitet. Die Plugins werden durch die Host-App unter `/plugins/<plugin-id>` gemountet. Alle Pfade unten sind relativ zur konfigurierbaren Serverbasis, standardmäßig `https://tools.d-razz.de/`.
|
|
|
|
## Authentifizierung
|
|
|
|
Die Host-App schützt alle Pfade außer exakt `/api/health` optional mit HTTP Basic Auth. Ist `APP_PASSWORD` gesetzt, muss der Client `Authorization: Basic <base64(username:password)>` senden. Der Standard-Benutzername des Servers ist `admin`, sofern `APP_USERNAME` nicht gesetzt wurde.
|
|
|
|
Fehlerantwort bei fehlender oder falscher Anmeldung:
|
|
|
|
```json
|
|
{"detail":"Anmeldung erforderlich."}
|
|
```
|
|
|
|
Status: `401 Unauthorized`, Header `WWW-Authenticate: Basic realm="boehmitools"`.
|
|
|
|
## Host-Verbindungstest
|
|
|
|
### `GET /api/health`
|
|
|
|
Ohne Authentifizierung erreichbar. Antwortfelder laut Backend:
|
|
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"version": "1.0.0",
|
|
"plugins": {"trainingsplan":"ok","trainingstracker":"ok"},
|
|
"tandoor_configured": false,
|
|
"openai_configured": true,
|
|
"authentication_enabled": true,
|
|
"jobs_running": 0
|
|
}
|
|
```
|
|
|
|
Status: `200`. Die App prüft danach zusätzlich den authentifizierten Tracker-Health-Endpunkt.
|
|
|
|
## Trainingstracker
|
|
|
|
Basis: `/plugins/trainingstracker`
|
|
|
|
### `GET /api/health`
|
|
|
|
Liefert `ok`, Server-Datenpfade, Verfügbarkeit von OpenAI und die unterstützten Vertragsversionen:
|
|
|
|
- `plan_schema`
|
|
- `training_contract`
|
|
- `tracker_schema`
|
|
- `result_data`
|
|
- `prompt`
|
|
- `analysis_schema`
|
|
- `normalization`
|
|
|
|
Status: `200`, oder hostweit `401`.
|
|
|
|
### `GET /api/plans`
|
|
|
|
Antwort:
|
|
|
|
```json
|
|
{
|
|
"plans": [{
|
|
"id": "phase-1.json",
|
|
"filename": "phase-1.json",
|
|
"name": "Phase 1",
|
|
"title": "…",
|
|
"subtitle": "…",
|
|
"weeks": 8,
|
|
"days": 6,
|
|
"tracked": true,
|
|
"start_date": "",
|
|
"completed_sessions": 5,
|
|
"source_changed": false,
|
|
"plan_id": "phase-1",
|
|
"published_revision": 1,
|
|
"tracker_revision": 7
|
|
}],
|
|
"selected": "phase-1.json"
|
|
}
|
|
```
|
|
|
|
Status: `200`.
|
|
|
|
### `POST /api/plans/{plan_id}/select`
|
|
|
|
Kein Request-Body erforderlich. Antwort: `{"ok":true,"selected":"phase-1.json"}`.
|
|
|
|
Status: `200`; `404` mit `{"error":"Trainingsplan nicht gefunden"}`.
|
|
|
|
### `GET /api/plans/{plan_id}`
|
|
|
|
Antwort:
|
|
|
|
```json
|
|
{
|
|
"plan": { /* normalisierte veröffentlichte Planfassung */ },
|
|
"tracker": { /* Tracker-Schema 7 */ },
|
|
"analysis_catalog": { /* Wochen- und Gesamtstatus */ },
|
|
"equivalence_guide": { /* Variantencluster und Fallback-FAQ */ },
|
|
"capabilities": {"openai": true}
|
|
}
|
|
```
|
|
|
|
`plan` enthält ausschließlich vom Backend erzeugte Felder wie `source_file`, `source_hash`, `plan_id`, `schema_version`, `contract_version`, `compatibility`, `published_revision`, `published_at`, `name`, `title`, `subtitle`, `weeks`, `days`, `phases`, `phase_by_week`, `stages`, `exercise_catalog`, `front`, `training_format`.
|
|
|
|
`tracker` enthält mindestens `version`, `revision`, `source_file`, `source_hash`, `profile`, `progressions`, `sessions`, `week_statuses`, `created_at`, `updated_at`; für die GET-Antwort werden zusätzlich `source_changed`, `analysis_cache` und `analysis_state` zusammengesetzt.
|
|
|
|
Status: `200`; `404`; `400` bei nicht lesbarem Plan.
|
|
|
|
### `PUT /api/plans/{plan_id}/tracker`
|
|
|
|
Vollständiges Speichern, primär für Kompatibilität. Request entweder direkt Trackerobjekt oder:
|
|
|
|
```json
|
|
{"expected_revision":7,"tracker":{}}
|
|
```
|
|
|
|
Antwort:
|
|
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"updated_at": "…",
|
|
"revision": 8,
|
|
"analysis_catalog": {},
|
|
"analysis_state": {}
|
|
}
|
|
```
|
|
|
|
Status: `200`; `400` für ungültige Nutzdaten; `409` bei Revisionskonflikt; `413` über 5 MiB.
|
|
|
|
### `PATCH /api/plans/{plan_id}/tracker/session`
|
|
|
|
Der von der App verwendete Autosave-Vertrag:
|
|
|
|
```json
|
|
{
|
|
"expected_revision": 7,
|
|
"profile": {"start_date":"","display_name":"","plan_notes":""},
|
|
"week_statuses": {"1":{"status":"open"}},
|
|
"session_key": "w01-d01",
|
|
"session": {
|
|
"status": "in_progress",
|
|
"plan_id": "phase-1",
|
|
"plan_revision": 1,
|
|
"items": {}
|
|
}
|
|
}
|
|
```
|
|
|
|
`profile`, `week_statuses` und `session` sind jeweils optional. Ein Patch ersetzt die betreffende Session vollständig, nicht einzelne Felder innerhalb der Session.
|
|
|
|
Erlaubte Sessionstatus: `planned`, `in_progress`, `stopped`, `completed`.
|
|
|
|
Erlaubte Übungsstatus: `planned`, `completed`, `partial`, `skipped`. Bei `skipped` kann `skip_reason` gespeichert werden. Neue strukturierte Ergebnisse nutzen `result_data` Version 2:
|
|
|
|
```json
|
|
{
|
|
"version": 2,
|
|
"mode": "reps|seconds|minutes",
|
|
"laterality": "bilateral|unilateral",
|
|
"sides_mode": "same|separate",
|
|
"sets": 3,
|
|
"weight_kg": 8.0,
|
|
"values": [8,7,6],
|
|
"left_values": [8,7,6],
|
|
"right_values": [8,7,6]
|
|
}
|
|
```
|
|
|
|
Das Backend akzeptiert maximal 20 Sätze, Werte von 0 bis 100000 und genau ein gemeinsames Gewicht. Alte Freitextfelder `result`, `note`, `progression` bleiben erhalten.
|
|
|
|
Erfolg wie beim PUT. Konfliktantwort:
|
|
|
|
```json
|
|
{
|
|
"error":"Die Session wurde in einem anderen Tab oder Gerät geändert.",
|
|
"code":"revision_conflict",
|
|
"current_revision":8
|
|
}
|
|
```
|
|
|
|
Status: `409`. Die App darf dann nicht automatisch gegen Revision 8 überschreiben.
|
|
|
|
### `POST /api/plans/{plan_id}/analysis`
|
|
|
|
Request Woche:
|
|
|
|
```json
|
|
{"scope":"week","week":1}
|
|
```
|
|
|
|
Request Gesamtanalyse:
|
|
|
|
```json
|
|
{"scope":"overall"}
|
|
```
|
|
|
|
Unveränderte, bereits aktuelle Analyse: `200` mit `cached:true`, `selection`, `analysis_state`, `analysis_cache`, `analysis_catalog`.
|
|
|
|
Neuer Hintergrundjob: `202 Accepted` mit `cached:false`, `job`, `analysis_state`, `analysis_catalog`.
|
|
|
|
Fehler: `400` bei fehlender OpenAI-Konfiguration, ungültiger Woche oder fehlenden Daten. `409` wenn bereits eine Analyse läuft. `404` bei unbekanntem Plan.
|
|
|
|
### `GET /api/plans/{plan_id}/analysis/status`
|
|
|
|
Antwort enthält `analysis_state`, `analysis_cache`, `analysis_catalog`, `updated_at`. Die App pollt nur bei `analysis_state.status == "running"`.
|
|
|
|
Status: `200`; `400`; `404`.
|
|
|
|
### `GET /api/plans/{plan_id}/tracker/export`
|
|
|
|
Liefert die Sessiondatei als `application/json`; erzeugt bei Bedarf einen leeren Tracker. Status `200` oder `404`.
|
|
|
|
## Trainingsplan-Editor
|
|
|
|
Basis: `/plugins/trainingsplan`
|
|
|
|
### `GET /api/plans`
|
|
|
|
Antwort: `plans` mit `id`, `name`, `active`, `revision`, `published_revision`, `has_unpublished_changes`, plus `active`.
|
|
|
|
### `POST /api/plans`
|
|
|
|
Request:
|
|
|
|
```json
|
|
{"name":"Neue Phase","from":"optionale-plan-id","kind":"training"}
|
|
```
|
|
|
|
`kind` kann technisch auch `recipe` sein; die Android-App erstellt ausschließlich Trainingspläne. Antwort ist der öffentliche Wrapper mit `id`, `plan_id`, `name`, `revision`, `published_revision`, `updated_at`, `published_at`, `has_unpublished_changes`, `tracked_sessions`, `config`.
|
|
|
|
### `GET /api/plans/{pid}`
|
|
|
|
Öffentlicher Wrapper des Entwurfs. Status `200` oder `404`.
|
|
|
|
### `POST /api/plans/{pid}/select`
|
|
|
|
Setzt den aktiven Plan. Status `200` oder `404`.
|
|
|
|
### `POST /api/plans/{pid}`
|
|
|
|
Speichert den Entwurf:
|
|
|
|
```json
|
|
{"config":{},"expected_revision":4}
|
|
```
|
|
|
|
Antwort: `ok`, öffentlicher Wrapper, `validation` mit `errors` und `warnings`.
|
|
|
|
Konflikt: `409` mit `code:"revision_conflict"` und `current_revision`.
|
|
|
|
### `POST /api/plans/{pid}/validate`
|
|
|
|
Request `{"config":{}}`. Antwort: `errors`, `warnings`, normalisierte `config`, `diff`. `diff` enthält Zähler und stabile-ID-basierte Änderungen für `days`, `rotations`, `exercises`, `progression_steps`, außerdem `changes`, `total_changes`, `training_format_changed`, `plan_meta_changed`, `tracked_sessions`.
|
|
|
|
### `POST /api/plans/{pid}/publish`
|
|
|
|
Request `{"expected_revision":4}`. Erfolgsantwort: `ok`, Wrapper, `diff`, `validation`.
|
|
|
|
Status `400` bei Validierungsfehlern; `409` bei Revisionskonflikt.
|
|
|
|
### `POST /api/plans/{pid}/rename`
|
|
|
|
Request `{"name":"…"}`. Antwort `id`, `name`, `revision`. Status `400` bei leerem Namen, `404` bei unbekanntem Plan.
|
|
|
|
### `DELETE /api/plans/{pid}`
|
|
|
|
Antwort `{"ok":true,"active":"…"}`. Status `400`, wenn der letzte Plan gelöscht werden soll; `404` bei unbekanntem Plan.
|
|
|
|
### `GET /api/plans/{pid}/proposals`
|
|
|
|
Liefert die Vorschlagsdatei unverändert oder `{}`. Vorschläge enthalten unter anderem `id`, `status`, `scope_key`, `analysis_type`, `week`, `target`, `target_label`, `target_exercise_id`, `target_progression_id`, `target_step_id`, `suggested_change`, `reason`, `condition`, `manual_step`, `analysis_created_at`.
|
|
|
|
### `POST /api/plans/{pid}/proposals/{proposal_id}`
|
|
|
|
Request `{"status":"open|accepted|rejected|reviewed"}`. Antwort `ok`, `proposals`. Ungültiger Status: `400`.
|
|
|
|
### Weitere vorhandene Endpunkte
|
|
|
|
`GET /api/config`, `POST /api/config`, `GET /api/default`, `POST /api/reset`, `GET /api/plans/{pid}/export`, `POST /api/plans/import`, `POST /api/pdf` existieren. Die native App verwendet für den Kernbetrieb die planbezogenen Endpunkte; sie bearbeitet niemals Serverdateien direkt.
|