← API und WebhooksSchnittstelle · v1

Messwerte senden

Über diese Schnittstelle kommen Körperwerte von jeder Waage, App oder Automation zu training mcp. Woher sie stammen, spielt keine Rolle, das Format schon. Dein Sprachmodell liest die Werte anschließend über das Werkzeug body-metrics.

Adresse
POST https://api.training-mcp.app/api/ingest/v1/body

Token anlegen

Du brauchst ein eigenes Schnittstellen-Token. Es darf nur Messwerte an /api/ingest schicken. Lesen kann es nichts, und andere Routen erreicht es nicht. Ein MCP-Token oder das Token der App funktioniert hier nicht.

  1. Öffne im Kontobereich „Verbindungen“.
  2. Klicke bei „Eigene Messwerte“ auf „Schnittstellen-Token erzeugen“ und gib ihm einen Namen, etwa den der Waage oder der Automation.
  3. Kopier das Token. Es steht nur einmal im Klartext da. Verlierst du es, widerrufst du es und legst ein neues an.
Zu den Verbindungen

Ein Token je Gerät oder Automation hat einen Vorteil: Fällt eines in falsche Hände, widerrufst du nur dieses.

Anfrage

Ein POST mit JSON im Körper. Das Token steht im Header Authorization, mit „Bearer “ davor. Ein Aufruf darf bis zu 100 Messungen enthalten.

Header
Authorization: Bearer DEIN_TOKEN
Content-Type: application/json
Accept: application/json
Körper
{
  "measurements": [
    {
      "measured_at": "2026-10-05T07:12:00+02:00",
      "device": "Tanita RD-545",
      "context": "morning_fasted",
      "weight_kg": 96.05,
      "body_fat_pct": 30.1,
      "muscle_mass_kg": 63.4,
      "body_water_pct": 50.2,
      "bone_mass_kg": 3.3,
      "visceral_fat": 14,
      "bmr_kcal": 2034,
      "metabolic_age": 52,
      "segments": {
        "trunk": { "fat_pct": 34.6, "muscle_mass_kg": 33.1 },
        "left_leg": { "fat_pct": 24.0, "muscle_mass_kg": 10.9 }
      }
    }
  ]
}

Felder einer Messung

Pflicht ist nur measured_at, dazu mindestens ein Wert. Die Einheit steht im Feldnamen. Unbekannte Felder lehnt der Server ab, statt sie still zu übergehen. So fällt ein Tippfehler sofort auf und nicht erst nach Wochen.

FeldTypBereichBedeutung
measured_atstringISO 8601Zeitpunkt der Messung, ISO 8601 mit Zeitzone, etwa 2026-10-05T07:12:00+02:00. Ohne Zeitzone wird die Messung abgelehnt.
devicestring≤ 120Waage oder App als Freitext, höchstens 120 Zeichen. Steht später neben dem Wert.
contextstringmorning_fasted, morning_other, midday, evening, post_exercise, unknownBedingung der Messung. Vergleichbar sind nur Messungen unter gleicher Bedingung; den Trend tragen die nüchternen Morgenmessungen (morning_fasted). Ohne Angabe bleibt die Bedingung offen.
external_idstring≤ 120Deine eigene Kennung der Messung, höchstens 120 Zeichen. Dieselbe Kennung ein zweites Mal schreibt dieselbe Messung fort.
weight_kgnumber20 – 400Körpergewicht in Kilogramm.
body_fat_pctnumber1 – 75Körperfett in Prozent des Gewichts.
muscle_mass_kgnumber5 – 200Muskelmasse in Kilogramm.
body_water_pctnumber20 – 85Körperwasser in Prozent des Gewichts.
bone_mass_kgnumber0,5 – 10Knochenmasse in Kilogramm.
visceral_fatnumber1 – 59Viszerales Fett als Kennzahl der Waage, ohne Einheit.
bmr_kcalinteger500 – 5000Grundumsatz in Kilokalorien je Tag, ganze Zahl.
metabolic_ageinteger10 – 120Stoffwechselalter in Jahren, ganze Zahl.
bminumber10 – 80Body-Mass-Index, wie ihn die Waage ausgibt.
segmentsobjectWerte je Körperteil, siehe unten.

Segmente

Waagen mit Segmentmessung liefern Werte je Körperteil. Erlaubt sind trunk, left_arm, right_arm, left_leg und right_leg, jeweils mit fat_pct (1 bis 75) und muscle_mass_kg (0,1 bis 80). Fehlt ein Teil, bleibt er leer.

Antwort

Der Server prüft jede Messung für sich. Eine fehlerhafte kippt nicht die ganze Lieferung: Du bekommst je Messung einen Status in der Reihenfolge, in der du sie geschickt hast, dazu eine Zusammenfassung.

received
neu angenommen
updated
dieselbe Messung mit geänderten Werten, fortgeschrieben
known
genau so schon vorhanden, nichts geändert
rejected
abgelehnt, der Grund steht in reason
Antwort
{
  "results": [
    { "index": 0, "status": "received", "measured_at": "2026-10-05T05:12:00Z" },
    { "index": 1, "status": "rejected", "reason": "weight_kg is 960, outside 20 to 400." }
  ],
  "summary": { "received": 1, "rejected": 1 }
}

HTTP-Status

200
Die Lieferung wurde verarbeitet. Ob einzelne Messungen abgelehnt wurden, steht in results.
401
Kein oder ein widerrufenes Token.
403
Das Token gilt für diese Route nicht, oder die Einwilligung zur Verarbeitung von Gesundheitsdaten ist widerrufen (code consent_revoked).
422
measurements fehlt, ist leer oder hat mehr als 100 Einträge.
429
Mehr als 120 Aufrufe in der Minute. Warte die Zeit aus Retry-After ab.

Regeln

  • Wiederholbar: Dieselbe Messung zweimal ergibt einen Datensatz. Erkannt wird sie an external_id, ohne Kennung an Zeitpunkt und Gerät. Schick ruhig nach jedem Lauf deiner Automation den ganzen Tag noch einmal.
  • Fortschreiben ergänzt: Eine geänderte Messung überschreibt die geschickten Werte. Werte, die du diesmal weglässt, bleiben stehen.
  • Zeitpunkt mit Zone: measured_at braucht eine Zeitzone. Messungen mehr als zehn Minuten in der Zukunft lehnt der Server ab, das ist fast immer eine falsch gestellte Uhr.
  • Grenzen: höchstens 100 Messungen je Aufruf und 120 Aufrufe in der Minute. Zahlen werden auf zwei Nachkommastellen gerundet.
  • Nur schreiben: Über die Schnittstelle kommt nichts zurück. Gelesen werden die Werte über MCP (body-metrics) mit Quelle „ingest“ und dem Gerät aus device.
Bioimpedanz-Waagen messen Fett, Muskel und Wasser über den Widerstand des Körpers. Das hängt am Wasserhaushalt und an der Tageszeit. Vergleichbar sind Messungen unter gleichen Bedingungen, am besten morgens nüchtern. Dein Sprachmodell liest sie als Verlauf.

Beispiele

curl
curl -X POST https://api.training-mcp.app/api/ingest/v1/body \
  -H "Authorization: Bearer DEIN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"measurements":[{"measured_at":"2026-10-05T07:12:00+02:00","device":"Tanita RD-545","weight_kg":96.05,"body_fat_pct":30.1}]}'

Kurzbefehl auf dem iPhone

Für eine Waage, deren App nur einen Text zum Teilen anbietet, oder für Werte, die du von Hand eingibst:

  1. Neuer Kurzbefehl, bei Bedarf „Im Teilen-Menü anzeigen“ einschalten, Eingabe: Text.
  2. Mit „Text abgleichen“ die Zahlen herausziehen, etwa mit dem Muster Gewicht: ([0-9,]+) für das Gewicht. Das Komma mit „Text ersetzen“ gegen einen Punkt tauschen.
  3. „Wörterbuch“ mit den Feldern measured_at (Aktuelles Datum im Format ISO 8601), device und weight_kg anlegen, als Zahl, nicht als Text. Ein zweites Wörterbuch mit dem Schlüssel measurements und einer Liste aus dem ersten.
  4. „Inhalte von URL abrufen“: die Adresse oben, Methode POST, Header Authorization mit „Bearer “ und deinem Token, Header Accept application/json, Anfragetext JSON mit dem Wörterbuch.
  5. Zum Prüfen die Antwort mit „Ergebnis anzeigen“ ausgeben. Steht dort received oder known, ist die Messung da.

Home Assistant

Mit einem rest_command, ausgelöst durch eine Automation, sobald der Sensor der Waage einen neuen Wert meldet. Das Token gehört mit „Bearer “ davor in secrets.yaml.

YAML
# configuration.yaml
rest_command:
  training_mcp_body:
    url: https://api.training-mcp.app/api/ingest/v1/body
    method: POST
    headers:
      Authorization: !secret training_mcp_token   # "Bearer DEIN_TOKEN"
      Accept: application/json
    content_type: application/json
    payload: >
      {"measurements":[{
        "measured_at": "{{ now().isoformat() }}",
        "device": "Withings Body+",
        "weight_kg": {{ states('sensor.waage_gewicht') | float }},
        "body_fat_pct": {{ states('sensor.waage_fett') | float }}
      }]}

# automations.yaml
- alias: Waage an training mcp
  trigger:
    - platform: state
      entity_id: sensor.waage_gewicht
  action:
    - service: rest_command.training_mcp_body

Python

Python
import requests

r = requests.post(
    "https://api.training-mcp.app/api/ingest/v1/body",
    headers={"Authorization": "Bearer DEIN_TOKEN", "Accept": "application/json"},
    json={"measurements": [{
        "measured_at": "2026-10-05T07:12:00+02:00",
        "device": "Tanita RD-545",
        "weight_kg": 96.05,
        "body_fat_pct": 30.1,
    }]},
    timeout=10,
)
r.raise_for_status()
print(r.json()["summary"])

Maschinenlesbar

Die Schnittstelle beschreibt sich selbst als OpenAPI 3.1. Wer eine Anbindung bauen lässt, auch von einem Sprachmodell, gibt am besten diese Datei mit.

OpenAPI 3.1
https://api.training-mcp.app/api/ingest/v1/openapi.json

Datenschutz

Körperwerte sind Gesundheitsdaten. Sie liegen auf Servern in Deutschland und gehen nur an das Sprachmodell, das du selbst verbindest. Widerrufst du die Einwilligung zur Verarbeitung von Gesundheitsdaten, nimmt die Schnittstelle nichts mehr an. Löschst du dein Konto, sind auch diese Werte weg.

Datenschutzerklärung