API Reference

API Reference

Complete reference for the MTH Health REST API. All endpoints return JSON. Authentication uses a two-tier system: API keys for user management, and user tokens for user-scoped operations.

Base URL

Production
https://health-api.movetohappiness.com

All endpoint paths in this reference are relative to this base URL.

Headers

Include the appropriate authorization header with every request. Legacy custom headers are still accepted during development, but the preferred contract is Authorization: Bearer ....

API Key (user management)
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
User Token (connections, journal, scores)
Authorization: Bearer USER_TOKEN
Content-Type: application/json

Compatibility aliases: X-App-Api-Key for API keys and X-User-Token for user tokens.

Connections

Manage OAuth connections between users and wearable providers. All connection endpoints require a user token .

Dexcom is supported in this flow as a glucose provider. The dedicated activity endpoint below is intended for Fitbit, Garmin, and Whoop connections, not Dexcom.

POST/api/v1/users/{userId}/connections/sessions

Create an OAuth connect session. Returns an authorization URL to redirect the end user to.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID

Request body

FieldTypeRequiredDescription
providerstringYesOne of: Fitbit, Whoop, Garmin, Dexcom
redirectUrlstringYesURL to redirect to after authorization
scopesstringNoCustom OAuth scopes (null for defaults)

Example request

curl
curl -X POST \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/sessions \
  -H "Authorization: Bearer USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "Dexcom",
    "redirectUrl": "https://myapp.com/connect/callback",
    "scopes": null
  }'

Example response

200 OK
{
  "id": "f8a1b2c3-d4e5-6789-0abc-def123456789",
  "authorizationUrl": "https://sandbox-api.dexcom.com/v3/oauth2/login?...",
  "expiresAt": "2026-03-17T10:10:00Z"
}

Redirect the end user to authorizationUrl. After they grant permission, they are redirected back to your redirectUrl with ?success=true or ?success=false.

GET/api/v1/users/{userId}/connections

List all active connections for a user.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "provider": "Dexcom",
    "providerUserId": "dexcom-user-id",
    "status": "Active",
    "scopes": "offline_access",
    "tokenExpiresAt": "2026-03-24T10:00:00Z",
    "createdAt": "2026-03-17T10:00:00Z",
    "updatedAt": "2026-03-17T10:00:00Z"
  }
]
DELETE/api/v1/users/{userId}/connections/{connectionId}

Disconnect a provider. Revokes the OAuth token and stops data sync.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
connectionIdpathstring (UUID)The connection ID to disconnect

Example request

curl
curl -X DELETE \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/c1d2e3f4-a5b6-7890-cdef-123456789abc \
  -H "Authorization: Bearer USER_TOKEN"

Example response

204 No Content
(empty response body)
GET/api/v1/users/{userId}/connections/activity

Retrieve canonical daily activity summaries for a date range across one or more providers.

This is the preferred public read endpoint for daily activity summaries. Use the optional provider query parameter to scope the response to a single provider; omit it to return entries across all of the user's connected providers in the app.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
fromquerystringStart date in YYYY-MM-DD format
toquerystringEnd date in YYYY-MM-DD format
providerquerystringOptional provider filter, such as Fitbit or Garmin

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/activity?from=2026-03-10&to=2026-03-15&provider=Fitbit" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "connectionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "provider": "Fitbit",
    "date": "2026-03-15",
    "steps": 8432,
    "caloriesOut": 2180,
    "distanceMeters": 6340,
    "lightActiveMinutes": 42,
    "moderateActiveMinutes": 25,
    "vigorousActiveMinutes": 22,
    "sedentaryMinutes": 640,
    "floorsClimbed": 8
  }
]
GET/api/v1/users/{userId}/connections/{connectionId}/activity/{date}

Retrieve daily activity data for a specific connection and date.

This endpoint is only applicable to providers that expose daily activity summaries. Use it with Fitbit or Garmin connections. WHOOP uses the dedicated activity-load route documented below, and unsupported providers return 404 instead of an internal server error.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
connectionIdpathstring (UUID)The connection ID
datepathstringDate in YYYY-MM-DD format

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/c1d2e3f4-a5b6-7890-cdef-123456789abc/activity/2026-03-15 \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
{
  "steps": 8432,
  "caloriesOut": 2180,
  "distance": 6.34,
  "fairlyActiveMinutes": 25,
  "veryActiveMinutes": 22,
  "rawJson": "{...}"
}
GET/api/v1/users/{userId}/connections/activity-load

Retrieve canonical load-oriented activity data for a date range across one or more providers.

This is the preferred public read endpoint for WHOOP-style strain or load data. Use the optional provider query parameter to scope the response to a single provider; omit it to return entries across all matching providers.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
fromquerystringStart date in YYYY-MM-DD format
toquerystringEnd date in YYYY-MM-DD format
providerquerystringOptional provider filter, such as Whoop

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/activity-load?from=2026-03-10&to=2026-03-15&provider=Whoop" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "connectionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
    "provider": "Whoop",
    "date": "2026-03-15",
    "windowKind": "PhysiologicalCycle",
    "windowStartUtc": "2026-03-14T21:48:00Z",
    "windowEndUtc": "2026-03-15T07:12:00Z",
    "loadScore": 15.4,
    "loadScoreScale": "whoop-strain-0-21",
    "energyKilocalories": 612.5,
    "averageHeartRate": 70,
    "maxHeartRate": 188,
    "distanceMeters": null,
    "steps": null,
    "zoneDurationsJson": "{...}",
    "sourceConfidence": "ProviderNative"
  }
]
GET/api/v1/users/{userId}/connections/{connectionId}/activity-load/{date}

Retrieve canonical load-oriented activity data for a specific connection and date.

This route is intended for providers that expose strain or load-oriented day data. The current public implementation is primarily relevant for Whoop cycle data.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
connectionIdpathstring (UUID)The connection ID
datepathstringDate in YYYY-MM-DD format

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/c1d2e3f4-a5b6-7890-cdef-123456789abc/activity-load/2026-03-15 \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
{
  "date": "2026-03-15",
  "windowKind": "PhysiologicalCycle",
  "windowStartUtc": "2026-03-14T21:48:00Z",
  "windowEndUtc": "2026-03-15T07:12:00Z",
  "loadScore": 15.4,
  "loadScoreScale": "whoop-strain-0-21",
  "energyKilocalories": 612.5,
  "averageHeartRate": 70,
  "maxHeartRate": 188,
  "distanceMeters": null,
  "steps": null,
  "zoneDurationsJson": "{...}",
  "sourceConfidence": "ProviderNative"
}
GET/api/v1/users/{userId}/connections/glucose

Retrieve canonical glucose readings, events, and calibrations for a date range.

Use the optional provider query parameter to scope the response to a single provider, such as Dexcom. If omitted, the response includes glucose data from all of the user's connected glucose-capable providers.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID
fromquerystringStart date in YYYY-MM-DD format
toquerystringEnd date in YYYY-MM-DD format
providerquerystringOptional provider filter, such as Dexcom

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/glucose?from=2026-03-10&to=2026-03-15&provider=Dexcom" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
{
  "readings": [
    {
      "connectionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "provider": "Dexcom",
      "date": "2026-03-15",
      "systemTime": "2026-03-15T08:00:00Z",
      "displayTime": "2026-03-15T08:00:00Z",
      "value": 112,
      "trend": "Flat",
      "trendRate": 0,
      "unit": "mg/dL",
      "rateUnit": "mg/dL/min",
      "status": "Active",
      "transmitterId": "8G6F2",
      "recordId": "reading-1"
    }
  ],
  "events": [
    {
      "connectionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "provider": "Dexcom",
      "date": "2026-03-15",
      "systemTime": "2026-03-15T08:05:00Z",
      "displayTime": "2026-03-15T08:05:00Z",
      "eventType": "Exercise",
      "eventSubType": null,
      "value": null,
      "unit": null,
      "eventId": "event-1"
    }
  ],
  "calibrations": [
    {
      "connectionId": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "provider": "Dexcom",
      "date": "2026-03-15",
      "systemTime": "2026-03-15T08:10:00Z",
      "displayTime": "2026-03-15T08:10:00Z",
      "value": 110,
      "unit": "mg/dL"
    }
  ]
}
GET/api/v1/users/{userId}/connections/providers

List all available providers with the user's current connection status for each.

Parameters

NameInTypeDescription
userIdpathstring (UUID)The user's MTH Health ID

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/connections/providers \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "provider": {
      "name": "Whoop",
      "slug": "whoop",
      "authType": "OAuth2",
      "logoUrl": null,
      "supportedDataTypes": [
        "Sleep",
        "ActivitySession",
        "Recovery",
        "ActivityLoadDaily",
        "ProfileSnapshot",
        "BodyMeasurementSnapshot"
      ]
    },
    "connection": null
  },
  {
    "provider": {
      "name": "Dexcom",
      "slug": "dexcom",
      "authType": "OAuth2",
      "logoUrl": null,
      "supportedDataTypes": ["GlucoseReading", "GlucoseEvent", "GlucoseCalibration"]
    },
    "connection": {
      "id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
      "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "provider": "Dexcom",
      "providerUserId": "dexcom-user-id",
      "status": "Active",
      "scopes": "offline_access",
      "tokenExpiresAt": "2026-03-24T10:00:00Z",
      "createdAt": "2026-03-17T10:00:00Z",
      "updatedAt": "2026-03-17T10:00:00Z"
    }
  }
]

Journal Entries

Manage user-scoped nutrition journal entries. Manual meals, generic drinks, dedicated water or coffee logs, and AI-analyzed meal photos all use the same journal entry model and require a user token.

POST/api/v1/users/{userId}/journal-entries

Create a manual meal, generic drink, water, or coffee entry.

Example request

curl
curl -X POST \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/journal-entries \
  -H "Authorization: Bearer USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "entryKind": "Water",
    "consumedAtUtc": "2026-03-18T08:00:00Z",
    "nutrients": { "volumeMl": 500 }
  }'

Use Water and Coffee as dedicated entryKind values when you want them tracked separately from generic Drink entries.

Example response

201 Created
{
  "id": "b1c2d3e4-f5a6-7890-abcd-ef1234567890",
  "entryKind": "Water",
  "entrySource": "Manual",
  "analysisStatus": "None",
  "title": "Water",
  "notes": null,
  "consumedAtUtc": "2026-03-18T08:00:00Z",
  "journalDate": "2026-03-18",
  "timezone": "Europe/Brussels",
  "isUserEdited": false,
  "nutrients": {
    "caloriesKcal": null,
    "proteinGrams": null,
    "carbsGrams": null,
    "fatGrams": null,
    "fiberGrams": null,
    "sugarGrams": null,
    "sodiumMg": null,
    "caffeineMg": null,
    "volumeMl": 500
  },
  "items": [],
  "image": null,
  "createdAt": "2026-03-18T08:00:01Z",
  "updatedAt": "2026-03-18T08:00:01Z"
}
POST/api/v1/users/{userId}/journal-entries/scans

Upload a meal photo for async AI nutrition analysis. The request uses multipart/form-data and returns 202 Accepted with a journal entry in Pending status.

Most scan flows will use Meal, but the API accepts the same journal kind set: Meal, Drink, Water, and Coffee.

Example request

curl
curl -X POST \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/journal-entries/scans \
  -H "Authorization: Bearer USER_TOKEN" \
  -F "image=@lunch.jpg" \
  -F "entryKind=Meal" \
  -F "consumedAtUtc=2026-03-18T12:15:00Z" \
  -F "timezone=Europe/Brussels" \
  -F "notes=Lunch"

Example response

202 Accepted
{
  "id": "c2d3e4f5-a6b7-8901-bcde-f1234567890a",
  "entryKind": "Meal",
  "entrySource": "AiImage",
  "analysisStatus": "Pending",
  "title": "Meal",
  "notes": "Lunch",
  "consumedAtUtc": "2026-03-18T12:15:00Z",
  "journalDate": "2026-03-18",
  "timezone": "Europe/Brussels",
  "isUserEdited": false,
  "nutrients": {
    "caloriesKcal": null,
    "proteinGrams": null,
    "carbsGrams": null,
    "fatGrams": null,
    "fiberGrams": null,
    "sugarGrams": null,
    "sodiumMg": null,
    "caffeineMg": null,
    "volumeMl": null
  },
  "items": [],
  "image": {
    "id": "d3e4f5a6-b7c8-9012-cdef-1234567890ab",
    "storageProvider": "AzureBlob",
    "fileName": "lunch.jpg",
    "contentType": "image/jpeg",
    "sizeBytes": 284512,
    "width": null,
    "height": null,
    "createdAt": "2026-03-18T12:15:01Z",
    "updatedAt": "2026-03-18T12:15:01Z"
  },
  "createdAt": "2026-03-18T12:15:01Z",
  "updatedAt": "2026-03-18T12:15:01Z"
}
GET/api/v1/users/{userId}/journal-entries?date={date}

List all journal entries for one journal date.

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/journal-entries?date=2026-03-18" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "id": "b1c2d3e4-f5a6-7890-abcd-ef1234567890",
    "entryKind": "Water",
    "entrySource": "Manual",
    "analysisStatus": "None",
    "title": "Water",
    "notes": null,
    "consumedAtUtc": "2026-03-18T08:00:00Z",
    "journalDate": "2026-03-18",
    "timezone": "Europe/Brussels",
    "isUserEdited": false,
    "nutrients": {
      "caloriesKcal": null,
      "proteinGrams": null,
      "carbsGrams": null,
      "fatGrams": null,
      "fiberGrams": null,
      "sugarGrams": null,
      "sodiumMg": null,
      "caffeineMg": null,
      "volumeMl": 500
    },
    "itemCount": 0,
    "hasImage": false,
    "createdAt": "2026-03-18T08:00:01Z",
    "updatedAt": "2026-03-18T08:00:01Z"
  },
  {
    "id": "e4f5a6b7-c8d9-0123-def1-234567890abc",
    "entryKind": "Coffee",
    "entrySource": "Manual",
    "analysisStatus": "None",
    "title": "Coffee",
    "notes": null,
    "consumedAtUtc": "2026-03-18T09:30:00Z",
    "journalDate": "2026-03-18",
    "timezone": "Europe/Brussels",
    "isUserEdited": false,
    "nutrients": {
      "caloriesKcal": 2,
      "proteinGrams": null,
      "carbsGrams": null,
      "fatGrams": null,
      "fiberGrams": null,
      "sugarGrams": null,
      "sodiumMg": null,
      "caffeineMg": 95,
      "volumeMl": 240
    },
    "itemCount": 0,
    "hasImage": false,
    "createdAt": "2026-03-18T09:30:01Z",
    "updatedAt": "2026-03-18T09:30:01Z"
  }
]
GET/api/v1/users/{userId}/journal-entries/{entryId}

Fetch one entry with itemized nutrients and optional image metadata.

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/journal-entries/c2d3e4f5-a6b7-8901-bcde-f1234567890a \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
{
  "id": "c2d3e4f5-a6b7-8901-bcde-f1234567890a",
  "entryKind": "Meal",
  "entrySource": "AiImage",
  "analysisStatus": "Completed",
  "title": "Chicken breast + 1 more",
  "notes": "Lunch",
  "consumedAtUtc": "2026-03-18T12:15:00Z",
  "journalDate": "2026-03-18",
  "timezone": "Europe/Brussels",
  "isUserEdited": false,
  "nutrients": {
    "caloriesKcal": 428,
    "proteinGrams": 49,
    "carbsGrams": 12,
    "fatGrams": 18,
    "fiberGrams": 3,
    "sugarGrams": 2,
    "sodiumMg": 540,
    "caffeineMg": null,
    "volumeMl": null
  },
  "items": [
    {
      "id": "f5a6b7c8-d9e0-1234-ef12-34567890abcd",
      "name": "Chicken breast",
      "category": "Protein",
      "quantity": 150,
      "unit": "g",
      "estimatedWeightGrams": 150,
      "nutrients": {
        "caloriesKcal": 248,
        "proteinGrams": 46,
        "carbsGrams": 0,
        "fatGrams": 5,
        "fiberGrams": null,
        "sugarGrams": null,
        "sodiumMg": 410,
        "caffeineMg": null,
        "volumeMl": null
      },
      "confidence": 0.94,
      "sortOrder": 0,
      "createdAt": "2026-03-18T12:15:09Z",
      "updatedAt": "2026-03-18T12:15:09Z"
    },
    {
      "id": "a6b7c8d9-e0f1-2345-f123-4567890abcde",
      "name": "Rice",
      "category": "Carbohydrate",
      "quantity": 120,
      "unit": "g",
      "estimatedWeightGrams": 120,
      "nutrients": {
        "caloriesKcal": 180,
        "proteinGrams": 3,
        "carbsGrams": 12,
        "fatGrams": 13,
        "fiberGrams": 3,
        "sugarGrams": 2,
        "sodiumMg": 130,
        "caffeineMg": null,
        "volumeMl": null
      },
      "confidence": 0.88,
      "sortOrder": 1,
      "createdAt": "2026-03-18T12:15:09Z",
      "updatedAt": "2026-03-18T12:15:09Z"
    }
  ],
  "image": {
    "id": "d3e4f5a6-b7c8-9012-cdef-1234567890ab",
    "storageProvider": "AzureBlob",
    "fileName": "lunch.jpg",
    "contentType": "image/jpeg",
    "sizeBytes": 284512,
    "width": null,
    "height": null,
    "createdAt": "2026-03-18T12:15:01Z",
    "updatedAt": "2026-03-18T12:15:01Z"
  },
  "createdAt": "2026-03-18T12:15:01Z",
  "updatedAt": "2026-03-18T12:15:09Z"
}
PATCH/api/v1/users/{userId}/journal-entries/{entryId}

Update an existing entry to correct portions, nutrients, or missing items.

Example request

curl
curl -X PATCH \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/journal-entries/b1c2d3e4-f5a6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "name": "Chicken breast",
        "quantity": 150,
        "unit": "g",
        "nutrients": {
          "caloriesKcal": 248,
          "proteinGrams": 46
        }
      }
    ]
  }'

Example response

200 OK
{
  "id": "b1c2d3e4-f5a6-7890-abcd-ef1234567890",
  "entryKind": "Meal",
  "entrySource": "AiImage",
  "analysisStatus": "Completed",
  "title": "Chicken breast",
  "notes": null,
  "consumedAtUtc": "2026-03-18T12:15:00Z",
  "journalDate": "2026-03-18",
  "timezone": "Europe/Brussels",
  "isUserEdited": true,
  "nutrients": {
    "caloriesKcal": 248,
    "proteinGrams": 46,
    "carbsGrams": null,
    "fatGrams": null,
    "fiberGrams": null,
    "sugarGrams": null,
    "sodiumMg": null,
    "caffeineMg": null,
    "volumeMl": null
  },
  "items": [
    {
      "id": "f5a6b7c8-d9e0-1234-ef12-34567890abcd",
      "name": "Chicken breast",
      "category": "",
      "quantity": 150,
      "unit": "g",
      "estimatedWeightGrams": null,
      "nutrients": {
        "caloriesKcal": 248,
        "proteinGrams": 46,
        "carbsGrams": null,
        "fatGrams": null,
        "fiberGrams": null,
        "sugarGrams": null,
        "sodiumMg": null,
        "caffeineMg": null,
        "volumeMl": null
      },
      "confidence": null,
      "sortOrder": 0,
      "createdAt": "2026-03-18T12:18:00Z",
      "updatedAt": "2026-03-18T12:18:00Z"
    }
  ],
  "image": {
    "id": "d3e4f5a6-b7c8-9012-cdef-1234567890ab",
    "storageProvider": "AzureBlob",
    "fileName": "lunch.jpg",
    "contentType": "image/jpeg",
    "sizeBytes": 284512,
    "width": null,
    "height": null,
    "createdAt": "2026-03-18T12:15:01Z",
    "updatedAt": "2026-03-18T12:15:01Z"
  },
  "createdAt": "2026-03-18T12:15:01Z",
  "updatedAt": "2026-03-18T12:18:00Z"
}

OAuth Callbacks

These are system endpoints used internally by the OAuth flow. You do not call them directly, but you need to know the callback URLs when configuring your OAuth app credentials with each provider.

GET/api/v1/connections/callback

OAuth 2.0 callback endpoint. Used by Fitbit, Whoop, and Dexcom. Receives code and state query parameters. Redirects the user to the client's redirectUrl.

No authentication required. These callbacks are managed by MTH Health as part of the hosted OAuth flow.

Example request

Browser redirect
GET /api/v1/connections/callback?code=oauth-code-123&state=state-token-abc

Example response

302 Found
Location: https://myapp.com/connect/callback?success=true
GET/api/v1/connections/callback/oauth1

OAuth 1.0a callback endpoint. Used by Garmin. Receives oauth_token and oauth_verifier query parameters. Redirects the user to the client's redirectUrl.

No authentication required. This callback is managed by MTH Health as part of the hosted OAuth flow.

Example request

Browser redirect
GET /api/v1/connections/callback/oauth1?oauth_token=request-token&oauth_verifier=verifier-123

Example response

302 Found
Location: https://myapp.com/connect/callback?success=true

Scores

Retrieve computed health scores that combine data from sleep, activity, and recovery across all connected providers. All score endpoints require a user token .

The current score contract is built around sleep, activity, and recovery dimensions. Dexcom support does not add glucose-specific score fields to these endpoints.

GET/api/v1/scores/daily

Retrieve daily health scores for a date range.

Parameters

NameInTypeDescription
fromquerystringStart date in YYYY-MM-DD format (inclusive)
toquerystringEnd date in YYYY-MM-DD format (inclusive)

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/scores/daily?from=2026-03-10&to=2026-03-15" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "date": "2026-03-15",
    "sleepScore": 82,
    "activityScore": 71,
    "recoveryScore": 78,
    "overallScore": 77,
    "components": { ... }
  },
  {
    "date": "2026-03-14",
    "sleepScore": 75,
    "activityScore": 68,
    "recoveryScore": 80,
    "overallScore": 74,
    "components": { ... }
  }
]
GET/api/v1/scores/weekly

Retrieve weekly aggregated health scores for a date range.

Parameters

NameInTypeDescription
fromquerystringStart date in YYYY-MM-DD format (inclusive)
toquerystringEnd date in YYYY-MM-DD format (inclusive)

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/scores/weekly?from=2026-03-03&to=2026-03-16" \
  -H "Authorization: Bearer USER_TOKEN"

Example response

200 OK
[
  {
    "weekStartDate": "2026-03-10",
    "sleepScore": 80,
    "activityScore": 68,
    "recoveryScore": 75,
    "overallScore": 74,
    "daysWithData": 5
  },
  {
    "weekStartDate": "2026-03-03",
    "sleepScore": 77,
    "activityScore": 72,
    "recoveryScore": 70,
    "overallScore": 73,
    "daysWithData": 7
  }
]

Users

Manage users within your application. All user endpoints require an API key. Users represent end users of your application whose wearable data you want to access.

POST/api/v1/users

Create a user idempotently by external user ID. Returns the user object plus a freshly issued token for user-scoped operations.

Request body

FieldTypeRequiredDescription
externalUserIdstringYesYour application's unique identifier for the user
localestringNoUser locale (e.g., en-US, nl-BE)
timezonestringNoIANA timezone (e.g., Europe/Brussels)
metadataobjectNoArbitrary key-value metadata for your application

Example request

curl
curl -X POST \
  https://health-api.movetohappiness.com/api/v1/users \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalUserId": "user-123",
    "locale": "en-US",
    "timezone": "Europe/Brussels",
    "metadata": { "plan": "premium" }
  }'

Returns 201 Created when a new user is created, or 200 OK when the externalUserId already exists and a fresh token is issued for that user.

Example response

201 Created or 200 OK
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "appId": "e5f6g7h8-i9j0-1234-klmn-op5678901234",
  "externalUserId": "user-123",
  "status": "Active",
  "locale": "en-US",
  "timezone": "Europe/Brussels",
  "metadata": { "plan": "premium" },
  "token": "usr_tok_abc123def456ghi789...",
  "createdAt": "2026-03-17T10:00:00Z",
  "updatedAt": "2026-03-17T10:00:00Z"
}
GET/api/v1/users?external_user_id={externalUserId}

Find a user by their external user ID. Returns 404 if not found. The token is not returned by read endpoints.

Parameters

NameInTypeDescription
external_user_idquerystringThe external user ID to look up

Example request

curl
curl -X GET \
  "https://health-api.movetohappiness.com/api/v1/users?external_user_id=user-123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response

200 OK
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "appId": "e5f6g7h8-i9j0-1234-klmn-op5678901234",
  "externalUserId": "user-123",
  "status": "Active",
  "locale": "en-US",
  "timezone": "Europe/Brussels",
  "metadata": { "plan": "premium" },
  "createdAt": "2026-03-17T10:00:00Z",
  "updatedAt": "2026-03-17T10:00:00Z"
}
GET/api/v1/users/{id}

Retrieve a user by their MTH Health internal ID. The token is not returned by read endpoints.

Parameters

NameInTypeDescription
idpathstring (UUID)The user's MTH Health ID

Example request

curl
curl -X GET \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response

200 OK
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "appId": "e5f6g7h8-i9j0-1234-klmn-op5678901234",
  "externalUserId": "user-123",
  "status": "Active",
  "locale": "en-US",
  "timezone": "Europe/Brussels",
  "metadata": { "plan": "premium" },
  "createdAt": "2026-03-17T10:00:00Z",
  "updatedAt": "2026-03-17T10:00:00Z"
}
PATCH/api/v1/users/{id}

Partially update a user. Only include the fields you want to change. The token is not returned by update endpoints.

Parameters

NameInTypeDescription
idpathstring (UUID)The user's MTH Health ID

Request body (partial)

FieldTypeDescription
localestringUpdated locale
timezonestringUpdated timezone
metadataobjectUpdated metadata (replaces existing)

Example request

curl
curl -X PATCH \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "locale": "nl-BE",
    "metadata": { "plan": "enterprise" }
  }'

Example response

200 OK
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "appId": "e5f6g7h8-i9j0-1234-klmn-op5678901234",
  "externalUserId": "user-123",
  "status": "Active",
  "locale": "nl-BE",
  "timezone": "Europe/Brussels",
  "metadata": { "plan": "enterprise" },
  "createdAt": "2026-03-17T10:00:00Z",
  "updatedAt": "2026-03-19T09:30:00Z"
}
DELETE/api/v1/users/{id}

Soft-delete a user. The user's data is retained but the user is marked as inactive.

Parameters

NameInTypeDescription
idpathstring (UUID)The user's MTH Health ID

Example request

curl
curl -X DELETE \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response

204 No Content
(empty response body)
POST/api/v1/users/{id}/rotate-token

Rotate a user's token. Invalidates the current token and returns a new one.

Parameters

NameInTypeDescription
idpathstring (UUID)The user's MTH Health ID

Example request

curl
curl -X POST \
  https://health-api.movetohappiness.com/api/v1/users/a1b2c3d4-e5f6-7890-abcd-ef1234567890/rotate-token \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response

200 OK
{
  "token": "usr_tok_new123xyz456abc789..."
}

Error codes

The API uses standard HTTP status codes to indicate the outcome of a request.

StatusMeaningDescription
400Bad RequestInvalid request body or missing required fields
401UnauthorizedMissing or invalid API key / user token
403ForbiddenValid credentials but insufficient permissions for this endpoint
404Not FoundResource does not exist
500Internal Server ErrorSomething went wrong on our end