Features Integrations AI & API Pricing Blog Docs
Overview WHOOP Withings Apple Health REST API AI & Claude MCP Server

REST API

The VitalTrends API lets you query your own health data programmatically. Build scripts, notebooks, automations, or pipe your data into any tool you like.

Pro feature. API access requires an active VitalTrends subscription. Generate your API key in Settings → Developer after logging in.

Authentication

All API requests must include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Keep your API key secret. Regenerate it from the Developer settings page if it is ever exposed.


Base URL

https://vitaltrends.net/api/v1

All endpoints return JSON. Dates are ISO 8601 strings (YYYY-MM-DD). Timestamps are UTC.


Endpoints

WHOOP

MethodPathDescription
GET /whoop/daily Recovery, HRV, RHR, sleep score, and strain per day
GET /whoop/workouts Workout records with sport, duration, and heart rate zones
GET /whoop/sleep Sleep sessions with stages and performance scores

Withings

MethodPathDescription
GET /withings/measurements Weight, body fat, muscle mass, and bone mass readings

Apple Health

MethodPathDescription
GET /apple-health/daily-summary Everything for a single day in one call: activity, heart, sleep stages, body, workouts
GET /apple-health/daily Paginated daily totals across a date range (legacy wide-table shape)
GET /apple-health?type=<type> Per-type time series. Append &include=metadata to surface sleep stages and workout details.

Daily summary, one request for a full picture

Use this when you want the morning-dashboard shape: every metric for a given date, including a sleep stage breakdown (deep, rem, core, awake, in_bed) and full workout metadata (sport, duration, HR min/avg/max, energy, flights climbed).

ParameterTypeDefaultDescription
datedatetoday (UTC)Single day, YYYY-MM-DD
typescsvallSubset to include. Any of: activity, heart, sleep, body, workouts
curl -s "https://vitaltrends.net/api/v1/apple-health/daily-summary?date=2026-04-21" \
  -H "Authorization: Bearer YOUR_API_KEY" | jq .
{
  "data": {
    "date": "2026-04-21",
    "activity": {
      "steps": 12500,
      "distance_km": 8.234,
      "active_energy_kcal": 487.2,
      "basal_energy_kcal": 1789.4,
      "apple_move_time_min": 45,
      "time_in_daylight_min": 87,
      "apple_stand_hours": 12
    },
    "heart": {
      "avg_heart_rate": 68,
      "min_heart_rate": 52,
      "max_heart_rate": 134,
      "resting_heart_rate": 56,
      "hrv_ms": 45.2,
      "respiratory_rate": 14.2,
      "spo2_pct": 97.8
    },
    "sleep": {
      "total_minutes": 452,
      "start_time": "2026-04-20T23:14:00+00:00",
      "end_time": "2026-04-21T06:46:00+00:00",
      "stages": {
        "deep_min": 68,
        "rem_min": 92,
        "core_min": 256,
        "light_min": 0,
        "awake_min": 36,
        "in_bed_min": 480,
        "unknown_min": 0
      },
      "sources": ["Apple Watch"]
    },
    "body": {
      "weight_kg": 75.20,
      "body_fat_pct": 18.40,
      "lean_body_mass_kg": 61.30,
      "bmi": 23.4,
      "height_m": 1.79
    },
    "workouts": [
      {
        "uuid": "018f0a3b-1c7e-7d9a-8a2b-8c5c47b3d401",
        "type": "Functional Strength Training",
        "sport_key": "functional_strength_training",
        "start_time": "2026-04-21T07:02:00+00:00",
        "end_time": "2026-04-21T07:47:00+00:00",
        "duration_min": 45,
        "active_energy_kcal": 320,
        "distance_m": null,
        "avg_heart_rate": 132,
        "min_heart_rate": 85,
        "max_heart_rate": 165,
        "flights_climbed": 3,
        "elevation_gain_m": null,
        "source": "Apple Watch"
      }
    ],
    "meta": {
      "unavailable_types": ["apple_exercise_time", "apple_stand_time", "vo2_max"],
      "unavailable_reason": "Not ingested by the VitalTrends iOS companion app yet."
    }
  }
}
Multi-source. When both iPhone and Apple Watch record the same metric (e.g. steps), the summary returns the larger per-source total instead of summing them, so two devices never double-count.

Per-type time series, with optional metadata

Use this when you want raw samples, a date range, or per-segment sleep stages. Pass include=metadata to reveal the metadata field (sleep stage, workout type, labels).

curl -s "https://vitaltrends.net/api/v1/apple-health?type=sleep&start=2026-04-20&end=2026-04-21&include=metadata" \
  -H "Authorization: Bearer YOUR_API_KEY" | jq .
{
  "data": [
    {
      "data_type": "sleep",
      "date": "2026-04-20",
      "start_time": "2026-04-21T01:45:00+00:00",
      "end_time": "2026-04-21T05:45:00+00:00",
      "value": 0,
      "value_min": null,
      "value_max": null,
      "sample_count": 1,
      "unit": "hr",
      "source": "Apple Watch",
      "metadata": { "stage": "core" }
    },
    {
      "data_type": "sleep",
      "date": "2026-04-20",
      "start_time": "2026-04-20T23:15:00+00:00",
      "end_time": "2026-04-21T00:15:00+00:00",
      "value": 0,
      "value_min": null,
      "value_max": null,
      "sample_count": 1,
      "unit": "hr",
      "source": "Apple Watch",
      "metadata": { "stage": "deep" }
    }
  ],
  "links": { "first": "...", "last": null, "prev": null, "next": null },
  "meta": { "current_page": 1, "from": 1, "path": "...", "per_page": 50, "to": 2 }
}

Valid type values

CategoryValues
Activity steps, distance_walking_running, active_energy_burned, basal_energy_burned, apple_move_time, apple_stand_hour, time_in_daylight, physical_effort, swimming_stroke_count_qty, workout_effort_score, estimated_workout_effort_score
Heart & vitals heart_rate, resting_heart_rate, heart_rate_variability, heart_rate_recovery, respiratory_rate, oxygen_saturation, blood_pressure_systolic, blood_pressure_diastolic, blood_glucose, body_temperature, afib_burden
Sleep sleep, apple_sleeping_breathing_disturbances, sleep_apnea_event
Workouts workouts
Body composition body_mass, body_fat_percentage, lean_body_mass, body_mass_index, height
Mobility walking_double_support, walking_steadiness, stair_ascent_speed, stair_descent_speed, six_minute_walk_distance
Running & cycling running_power, cycling_power, cycling_speed
Water sports underwater_depth, water_temperature, distance_paddle_sports, paddle_sports_speed, distance_rowing, rowing_speed
Winter sports distance_cross_country_skiing, cross_country_skiing_speed, distance_skating_sports
Fitness events low_cardio_fitness_event

Availability depends on which HealthKit sensors and iOS version your device supports. Types that are defined but not yet ingested by the VitalTrends iOS companion app are listed in meta.unavailable_types on the daily summary response.


Query parameters

All list endpoints support the following parameters:

ParameterTypeDefaultDescription
startdate30 days agoInclusive start date (YYYY-MM-DD)
enddatetodayInclusive end date (YYYY-MM-DD)
per_pageinteger50Records per page (max 200)
pageinteger1Page number (1-indexed)

Example request

curl -s "https://vitaltrends.net/api/v1/whoop/daily?start=2024-01-01&per_page=7" \
  -H "Authorization: Bearer YOUR_API_KEY" | jq .

Example response

{
  "data": [
    {
      "date": "2024-01-07",
      "recovery_score": 82,
      "hrv_rmssd_milli": 68.4,
      "resting_heart_rate": 48,
      "sleep_performance_pct": 89,
      "sleep_duration_minutes": 450,
      "strain": 12.4
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 7,
    "total": 7,
    "from": 1,
    "to": 7
  }
}

Rate limits

The API allows 500 requests per minute per API key. If you exceed the limit, requests return 429 Too Many Requests with a Retry-After header.


Error responses

StatusMeaning
401Missing or invalid API key
403Valid key but subscription required
422Invalid query parameters
429Rate limit exceeded
500Server error, try again shortly

Need an endpoint that is not listed here? Get in touch and we will consider adding it.