{"openapi":"3.1.0","info":{"title":"VytalLink Health Data API","description":"API for authenticating users and retrieving health metrics from connected devices, including grouping and aggregation options, with WebSocket bridging and MCP tool support.","version":"1.0.0"},"servers":[{"url":"http://localhost:8000","description":"VytalLink Backend Server"}],"paths":{"/logout":{"get":{"summary":"Logout","description":"Logout endpoint - clears session","operationId":"logout","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Logged out successfully"}},"required":["message"]}}}}}}},"/api/direct-login":{"post":{"summary":"Authenticate immediately with the word/code pair from the app.","description":"Simple direct login endpoint with conversation-based authentication.\nAccepts word + code combination and stores session by conversation ID.\nGPT clients send openai-conversation-id header for chat isolation.","operationId":"direct_login","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"word":{"type":"string","description":"Connection word from mobile app, a keyword like 'apple', 'island', etc.","example":"island"},"code":{"type":"string","description":"6-digit PIN shown in the VytalLink app Settings screen. Field name is 'code', not 'pin'.","example":"343786"}},"required":["word","code"]}}}},"responses":{"200":{"description":"Direct login. Authenticate with word and code from the mobile application to get an immediate access token. This streamlined flow bypasses the full OAuth code exchange and provides instant authentication. If the user still needs the vytalLink app, point them to https://vytallink.xmartlabs.com/ to install it and retrieve their word/code pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectLoginResponse"}}}}}}},"/api/summary":{"post":{"summary":"Retrieve a health summary across multiple metrics.","description":"Protected endpoint to request a health summary from the phone.\nSupports Bearer token and conversation-based authentication (openai-conversation-id).\nForwards a summary_request over the user's phone WebSocket connection and awaits a response.","operationId":"get_summary","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"start_time":{"type":"string","description":"Start time in ISO format (e.g., 2024-01-01T00:00:00Z)"},"end_time":{"type":"string","description":"End time in ISO format (e.g., 2024-12-31T23:59:59Z)"},"metrics":{"type":"array","description":"Optional list of metric requests; if omitted, device defaults apply.","items":{"type":"object","properties":{"value_type":{"type":"string","enum":["STEPS","HEART_RATE","CALORIES","BLOOD_OXYGEN","BLOOD_PRESSURE","BODY_TEMPERATURE","BODY_METRICS","GLUCOSE","EXERCISE_TIME","RESPIRATORY_RATE","WALKING_SPEED","SLEEP","MINDFULNESS","WORKOUT","DISTANCE"],"description":"Metric category to include"},"group_by":{"type":"string","enum":["HOUR","DAY","WEEK","MONTH"],"description":"Aggregation bucket"},"statistic":{"type":"string","enum":["SUM","AVERAGE"],"description":"Aggregation statistic"}},"required":["value_type"]}}},"required":["start_time","end_time"]}}}},"responses":{"200":{"description":"Request a summary from the connected device for a given time window, optionally specifying metric/grouping/statistic overrides. Metrics follow VytalLink categories and can include steps, calories, distance, workouts, sleep, etc.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSummaryResponse"}}}}}}},"/api/get_health_metrics":{"get":{"summary":"Retrieve aggregated health metrics from connected devices.","description":"Request a health metric within a specific time range (schema-aligned with GPT OpenAPI).\nSupports both Bearer token and conversation-based authentication.\nReturns 200 with {healthData, count, success, error_message} or 404/504 per device state.","operationId":"get_health_metrics","security":[{"BearerAuth":[]}],"parameters":[{"name":"value_type","in":"query","required":true,"schema":{"type":"string","enum":["STEPS","HEART_RATE","CALORIES","BLOOD_OXYGEN","BLOOD_PRESSURE","BODY_TEMPERATURE","BODY_METRICS","GLUCOSE","EXERCISE_TIME","RESPIRATORY_RATE","WALKING_SPEED","SLEEP","MINDFULNESS","WORKOUT","DISTANCE"]},"description":"Type of metric to retrieve. Options: STEPS (number of steps — unit: count), HEART_RATE (beats per minute, including resting — unit: beats_per_minute), CALORIES (total and active calories burned — unit: kcal), BLOOD_OXYGEN (blood oxygen saturation — unit: percent), BLOOD_PRESSURE (systolic and diastolic — unit: mmHg), BODY_TEMPERATURE (body temperature — unit: celsius), BODY_METRICS (weight, height, body fat, water, nutrition — units vary), GLUCOSE (blood glucose level — unit: mg/dL), EXERCISE_TIME (minutes of exercise — unit: minute), RESPIRATORY_RATE (breaths per minute — unit: breaths_per_minute), WALKING_SPEED (walking speed — unit: m/s), SLEEP (sleep duration — unit: minute; use AVERAGE statistic for per-night average, SUM for total), MINDFULNESS (minutes of meditation — unit: minute), WORKOUT (recorded physical activities — value is an object with fields: workout_type, session_count, total_distance, total_energy_burned, total_steps), DISTANCE (distance covered walking/running — unit: meter). IMPORTANT: the response type field may differ from value_type — SLEEP requests return type: SLEEP_SESSION; GLUCOSE returns type: BLOOD_GLUCOSE; DISTANCE returns type: DISTANCE_WALKING_RUNNING or DISTANCE_DELTA; CALORIES returns type: TOTAL_CALORIES_BURNED or ACTIVE_ENERGY_BURNED; BLOOD_PRESSURE returns type: BLOOD_PRESSURE_SYSTOLIC and BLOOD_PRESSURE_DIASTOLIC; HEART_RATE returns type: HEART_RATE and RESTING_HEART_RATE. Never use response type values as value_type inputs."},{"name":"start_time","in":"query","required":true,"schema":{"type":"string"},"description":"Start time in ISO format (e.g., 2024-01-01T00:00:00Z)","example":"2025-09-07T00:00:00Z"},{"name":"end_time","in":"query","required":true,"schema":{"type":"string"},"description":"End time in ISO format (e.g., 2024-01-02T00:00:00Z)","example":"2025-09-07T23:59:59Z"},{"name":"group_by","in":"query","required":false,"schema":{"type":"string","enum":["HOUR","DAY","WEEK","MONTH"]},"description":"Time bucketing of results. ALWAYS set this when the user wants summaries per period (e.g., per day, week, month) so the server aggregates before returning data. Valid values: HOUR, DAY, WEEK, MONTH. Omit only when the user needs raw event timestamps."},{"name":"statistic","in":"query","required":false,"schema":{"type":"string","enum":["AVERAGE","SUM"]},"description":"Aggregation to apply to grouped data. REQUIRED whenever 'group_by' is provided. Use 'AVERAGE' for mean values (sleep minutes per night with an average) or 'SUM' for totals (total minutes slept). Choosing a statistic is what enables the backend to return compact summaries."}],"responses":{"200":{"description":"Get health metrics for a specific time period. Retrieves health data from connected devices including steps, heart rate, calories, sleep data, and more. Always request aggregated data (using 'group_by' and 'statistic') when a user asks for totals per day, week, or month so the response stays compact. Only omit aggregation when the user explicitly needs individual event timestamps. IMPORTANT: Results may include data from multiple devices (different source_id values) for the same time period. To avoid double-counting, pick the single source_id with the most data points and use only that source's values. Never sum across different source_id's for the same metric. Access requires the vytalLink companion app (download at https://vytallink.xmartlabs.com/) to share wearable or mobile health data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetHealthMetricsResponse"}}}}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Bearer token obtained from /api/direct-login"}},"schemas":{"GetApiDocsResponse":{"type":"object","properties":{"content":{"type":"string","description":"Full API reference in markdown format"},"success":{"type":"boolean"}}},"GetHealthMetricsResponse":{"type":"object","properties":{"healthData":{"type":"array","description":"Array of health data items","items":{"type":"object","properties":{"type":{"type":"string","description":"Health data type in the response — may differ from the value_type you requested. Examples: SLEEP request → SLEEP_SESSION; GLUCOSE → BLOOD_GLUCOSE; BLOOD_PRESSURE → BLOOD_PRESSURE_SYSTOLIC / BLOOD_PRESSURE_DIASTOLIC. Do not use response type values as value_type inputs.","example":"STEPS"},"value":{"description":"Health data value — number for most metrics (steps, heart rate, sleep minutes, etc.), object for workout/nutrition types"},"unit":{"type":"string","description":"Unit of measurement","example":"COUNT"},"date_from":{"type":"string","description":"Start date of the measurement period","example":"2025-09-07T00:00:00.000Z","format":"date-time"},"date_to":{"type":"string","description":"End date of the measurement period","example":"2025-09-07T23:59:59.000Z","format":"date-time"},"source_platform":{"type":"string","description":"Platform that provided the data","example":"googleHealthConnect"},"source_device_id":{"type":"string","description":"ID of the source device"},"source_id":{"type":"string","description":"Unique identifier from the source"},"source_name":{"type":"string","description":"Name of the data source"}},"required":["type","value","unit","date_from","date_to"]}},"count":{"type":"integer","description":"Number of health data items returned","example":1},"success":{"type":"boolean","description":"Indicates if the request was successful","example":true},"error_message":{"type":"string","description":"Error message if success is false"}},"required":["healthData","count","success"]},"GetHealthMetricsItem":{"type":"object","properties":{"type":{"type":"string","description":"Health data type in the response — may differ from the value_type you requested. Examples: SLEEP request → SLEEP_SESSION; GLUCOSE → BLOOD_GLUCOSE; BLOOD_PRESSURE → BLOOD_PRESSURE_SYSTOLIC / BLOOD_PRESSURE_DIASTOLIC. Do not use response type values as value_type inputs.","example":"STEPS"},"value":{"description":"Health data value — number for most metrics (steps, heart rate, sleep minutes, etc.), object for workout/nutrition types"},"unit":{"type":"string","description":"Unit of measurement","example":"COUNT"},"date_from":{"type":"string","description":"Start date of the measurement period","example":"2025-09-07T00:00:00.000Z","format":"date-time"},"date_to":{"type":"string","description":"End date of the measurement period","example":"2025-09-07T23:59:59.000Z","format":"date-time"},"source_platform":{"type":"string","description":"Platform that provided the data","example":"googleHealthConnect"},"source_device_id":{"type":"string","description":"ID of the source device"},"source_id":{"type":"string","description":"Unique identifier from the source"},"source_name":{"type":"string","description":"Name of the data source"}},"required":["type","value","unit","date_from","date_to"]},"GetSummaryResponse":{"type":"object","description":"Summary payload returned by the connected device. Contains a healthData array with items per metric and period, similar to get_health_metrics.","properties":{"healthData":{"type":"array","description":"Array of health data items across requested metrics","items":{"type":"object","properties":{"type":{"type":"string","description":"Metric type (e.g. STEPS, CALORIES)"},"value":{"description":"Metric value — number for most metrics, object for WORKOUT"},"unit":{"type":"string","description":"Unit of measurement"},"date_from":{"type":"string","format":"date-time"},"date_to":{"type":"string","format":"date-time"},"source_id":{"type":"string","description":"Data source identifier"}},"required":["type","value","unit","date_from","date_to"]}},"count":{"type":"integer","description":"Total items returned"},"success":{"type":"boolean"}},"required":["healthData","count","success"]},"GetSummaryItem":{"type":"object","properties":{"type":{"type":"string","description":"Metric type (e.g. STEPS, CALORIES)"},"value":{"description":"Metric value — number for most metrics, object for WORKOUT"},"unit":{"type":"string","description":"Unit of measurement"},"date_from":{"type":"string","format":"date-time"},"date_to":{"type":"string","format":"date-time"},"source_id":{"type":"string","description":"Data source identifier"}},"required":["type","value","unit","date_from","date_to"]},"DirectLoginResponse":{"type":"object","properties":{"success":{"type":"boolean","description":"Indicates if authentication was successful","example":true},"access_token":{"type":"string","description":"Bearer token for API requests"},"token_type":{"type":"string","description":"Type of the token","example":"Bearer"},"expires_in":{"type":"integer","description":"Token expiration time in seconds","example":7200},"user_id":{"type":"string","description":"Unique identifier for the authenticated user"},"user_name":{"type":"string","description":"Display name of the authenticated user"},"message":{"type":"string","description":"Success message"},"error_code":{"type":"string","description":"Machine-readable authentication error code when success is false"}},"required":["success","message"]},"GetUserInfoResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique user identifier"},"user_name":{"type":"string","description":"Display name of the user"},"email":{"type":"string","description":"User email address"},"created_at":{"type":"string","description":"Account creation timestamp","format":"date-time"},"active":{"type":"boolean","description":"Whether the user account is active","example":true}},"required":["id","user_name","active"]}}}}