API reference

Health

Your own health data, sync, sharing, Sexual Activity, export and delete; what others share with you; Mirage server leaderboards.

See Health. /v1/me/health is always the caller's own data and /v1/health what others share with them. Health belongs to people, never an organization: personal keys act for their maker only when the person allowed it in Health → Privacy, and privacy settings change only in the apps.

GET /v1/me/health/profile

Your Health settings: the consent you agreed to (and each sensitive category's), time zone, pinned metrics, Caity's and API access, Sexual Activity's sharing, and whether your account is known to be 18 or over (adult, ageUnknown; never the date of birth itself).

Auth: user access token or platform agent key

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

PATCH /v1/me/health/profile

Changes your time zone (days are your local days) or Summary's pinned metrics (pinned, up to 12, in order).

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
timeZonestringNoup to 64 characters
pinnedstring[]Noup to 12 items; each up to 48 characters

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

POST /v1/me/health/consent

Agrees to Health's terms (version, the current one). Nothing is stored before. In the app only.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
versionintegerYes

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

Withdraws consent: nothing new is stored, every share and leaderboard opt-in ends, Caity's and API access turn off. Your data stays until you delete it. In the app only.

Auth: user access token or platform agent key

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

Turns a sensitive category on or off (on): Cycle Tracking, Medications, Mental Wellbeing, Symptoms, and Sexual Activity (18 or over). Off ends its sharing. In the app only.

Auth: user access token or platform agent key

Path parameterDescription
:categoryA Health category: activity, body, cycle, hearing, heart, medications, mental, mindfulness, mobility, nutrition, respiratory, sleep, symptoms, vitals, sexual or other.

Request body

FieldTypeRequiredNotes
onbooleanYes

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

PUT /v1/me/health/assistant

Caity's access (enabled, categories): summaries only; standard categories unless you name some, sensitive ones only when named, Sexual Activity never. In the app only.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredDefaultNotes
enabledbooleanYes
categories("activity" | "body" | "cycle" | "hearing" | "heart" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual" | "other")[]No[]up to 16 items

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

PUT /v1/me/health/api-access

Lets personal API keys and connected apps with health:read or health:write act for you (on). Off by default. In the app only.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
onbooleanYes

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/me/health/metrics

The metric registry as you can use it (Sexual Activity only when you're known to be 18 or over), the categories, and your state for each metric you have data in (count, first and last sample, months, unit, sharing).

Auth: user access token or platform agent key

Response 200

{
  metrics: {
    metricId: string
    label: string
    category: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    kind: "duration" | "event" | "category" | "quantity"
    unit: string
    units: {
      id: string
      label: string
      factor: number
      offset?: number
    }[]
    aggregation: "duration" | "count" | "sum" | "average" | "latest"
    decimals: number
    sensitivity: "standard" | "sensitive" | "sexual"
    values?: {
      value: number
      label: string
    }[]
    healthKit?: {
      identifier: string
      kind: "category" | "quantity" | "workout"
      unit?: string
      readOnly?: boolean
      factor?: number
      categoryValues?: number[]
    }
    healthConnect?: string
    leaderboard?: "count" | "sum" | "average"
    min?: number
    max?: number
    pinned?: boolean
    description?: string
    enabled: boolean
    sortOrder: number
  }[]
  categories: {
    id: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    label: string
    glyph: "health-body" | "health-heart" | "health-other" | "health-activity" | "health-cycle" | "health-hearing" | "health-medications" | "health-mental" | "health-mindfulness" | "health-mobility" | "health-nutrition" | "health-respiratory" | "health-sleep" | "health-symptoms" | "health-vitals" | "health-sexual"
    sensitivity: "standard" | "sensitive" | "sexual"
    adultOnly?: true
  }[]
  states: {
    metricId: string
    unit?: string
    share?: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    count: number
    firstAt?: number
    lastAt?: number
    months: string[]
    updatedAt: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/summary

Summary: your pinned metrics (today, the last seven days, the average and the trend against the week before), highlights, and the categories you have data in.

Auth: user access token or platform agent key

Response 200

{
  pinned: {
    metricId: string
    latest: null | {
      value: number
      at: number
    }
    today: null | number
    week: (null | number)[]
    average: null | number
    trend: null | "flat" | "up" | "down"
  }[]
  highlights: {
    metricId: string
    text: string
    kind: "trend" | "best" | "streak"
  }[]
  today: string
  categories: {
    id: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    metrics: number
    lastAt: null | number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/metrics/:metricId/chart

A metric's chart: range D (hours of end), W and M (days), 6M (weeks) or Y (months), ending on end (a day; today by default), with the average, range, total and best day.

Auth: user access token or platform agent key

Path parameterDescription
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.
Query parameterTypeRequiredDefaultNotes
range"D" | "W" | "M" | "6M" | "Y"No"W"
endstringNomatches ^\d{4}-\d{2}-\d{2}$

Response 200

{
  metricId: string
  range: "M" | "D" | "W" | "6M" | "Y"
  buckets: {
    key: string
    from: string
    to: string
    value: null | number
    min: null | number
    max: null | number
    days: number
  }[]
  stats: {
    days: number
    average: null | number
    total: null | number
    min: null | number
    max: null | number
    best: null | {
      day: string
      value: number
    }
  }
  today: string
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/metrics/:metricId/samples

A metric's samples, newest first (limit up to 200; from and to in milliseconds; cursor from the last page). Sexual Activity's entries include their partner (name, userId), only ever to you.

Auth: user access token or platform agent key

Path parameterDescription
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.
Query parameterTypeRequiredNotes
cursorstringNoup to 2,000 characters
fromintegerNocoerced from a string
tointegerNocoerced from a string
limitintegerNo1–200; coerced from a string

Response 200

{
  samples: {
    sampleId: string
    metricId: string
    start: number
    end: number
    value: number
    stage?: number
    protection?: boolean | null
    partner?: {
      name?: string
      userId?: string
    }
    note?: string
    meta?: {
      [key: string]: boolean | string | number
    }
    sourceId: string
    sourceName: string
    external: boolean
    version: number
    createdAt: number
    updatedAt: number
  }[]
  cursor: null | string
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

PUT /v1/me/health/metrics/:metricId/unit

The unit you see a metric in (unit, one of its units).

Auth: user access token or platform agent key

Path parameterDescription
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.

Request body

FieldTypeRequiredNotes
unitstringYesup to 20 characters

Also checked: Unknown fields are rejected.

Response 200

{
  metricId: string
  unit: string
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.

PATCH /v1/me/health/metrics/:metricId/samples/:sampleId

Changes an entry made in the apps (value in unit, times, note, protection, partner). Samples from HealthKit change there and sync here.

Auth: user access token or platform agent key

Path parameterDescription
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.
:sampleIdA Health sample's id (hsm_…).

Request body

FieldTypeRequiredNotes
startintegerNo≥ 0
endintegerNo≥ 0
valuenumberNo
unitstringNoup to 20 characters
stageintegerNo
protectionbooleanNocan be null
partnerobjectNocan be null
partner.namestringNo1–100 characters; trimmed
partner.userIdstringNo4–64 characters
notestringNoup to 1,000 characters
metaobjectNokeys up to 40 characters; values: string (up to 200 characters), number or boolean

Also checked: Unknown fields are rejected.

Response 200

{
  sample: {
    sampleId: string
    metricId: string
    start: number
    end: number
    value: number
    stage?: number
    protection?: boolean | null
    partner?: {
      name?: string
      userId?: string
    }
    note?: string
    meta?: {
      [key: string]: boolean | string | number
    }
    sourceId: string
    sourceName: string
    external: boolean
    version: number
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.

DELETE /v1/me/health/metrics/:metricId/samples/:sampleId

Deletes a sample; the day's values, totals and leaderboard scores follow.

Auth: user access token or platform agent key

Path parameterDescription
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.
:sampleIdA Health sample's id (hsm_…).

Response 204 with no body.

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
404Sample not found.

POST /v1/me/health/samples

Adds samples (entries in the apps, or a batch from elsewhere).

Auth: user access token or platform agent key

Request body (up to 2 MB)

FieldTypeRequiredNotes
samplesobject[]Yes1–500 items
samples[].metricIdstringYes1–48 characters
samples[].startintegerYes≥ 0
samples[].endintegerNo≥ 0
samples[].valuenumberNo
samples[].unitstringNoup to 20 characters
samples[].stageintegerNo
samples[].protectionbooleanNocan be null
samples[].partnerobjectNocan be null
samples[].partner.namestringNo1–100 characters; trimmed
samples[].partner.userIdstringNo4–64 characters
samples[].notestringNoup to 1,000 characters
samples[].metaobjectNokeys up to 40 characters; values: string (up to 200 characters), number or boolean
samples[].sourceobjectNo
samples[].source.kind"watch" | "phone" | "app" | "manual"Yes
samples[].source.namestringYes1–80 characters; trimmed
samples[].source.bundleIdstringNoup to 200 characters
samples[].source.devicestringNoup to 120 characters
samples[].externalIdstringNo1–100 characters
samples[].versionintegerNo≥ 0

Also checked: Unknown fields are rejected.

Response 201

{
  written: {
    sampleId: string
    metricId: string
    start: number
    end: number
    value: number
    stage?: number
    protection?: boolean | null
    partner?: {
      name?: string
      userId?: string
    }
    note?: string
    meta?: {
      [key: string]: boolean | string | number
    }
    sourceId: string
    sourceName: string
    external: boolean
    version: number
    createdAt: number
    updatedAt: number
  }[]
  skipped: {
    index: number
    reason: "older" | "duplicate" | "invalid"
    message?: string
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
413That's too much at once.

POST /v1/me/health/sync

The phone's HealthKit sync: new and changed samples, and ones deleted there.

Auth: user access token or platform agent key

Request body (up to 2 MB)

FieldTypeRequiredDefaultNotes
samplesany JSON[]No[]up to 500 items
removals(object | object)[]No[]up to 500 items

Also checked: Unknown fields are rejected.

Response 200

{
  written: number
  skipped: {
    index: number
    reason: "older" | "duplicate" | "invalid"
    message?: string
  }[]
  removed: number
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
413That's too much at once.

GET /v1/me/health/sync/changes

Entries made in the apps since cursor, for the phone to write to HealthKit.

Auth: user access token or platform agent key

Query parameterTypeRequiredNotes
cursorstringNoup to 100 characters

Response 200

{
  changes: {
    op: "delete"
    sampleId: string
    metricId: string
  } | {
    op: "put"
    sampleId: string
    metricId: string
    sample: {
      sampleId: string
      metricId: string
      start: number
      end: number
      value: number
      stage?: number
      protection?: boolean | null
      partner?: {
        name?: string
        userId?: string
      }
      note?: string
      meta?: {
        [key: string]: boolean | string | number
      }
      sourceId: string
      sourceName: string
      external: boolean
      version: number
      createdAt: number
      updatedAt: number
    }
  }[]
  cursor: string
  more: boolean
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/sources

Your data sources (the Watch, the phone, apps, entries made here) in order: where samples overlap, the first wins.

Auth: user access token or platform agent key

Response 200

{
  sources: {
    sourceId: string
    name: string
    kind: "watch" | "phone" | "app" | "manual"
    bundleId?: string
    device?: string
    priority: number
    lastSeenAt: number
    createdAt: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

PUT /v1/me/health/sources/order

Orders your sources (order: source ids, first wins; the rest keep their order after). Days changed from now on use it. In the app only.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
orderstring[]Yesup to 200 items; each 1–64 characters

Also checked: Unknown fields are rejected.

Response 200

{
  sources: {
    sourceId: string
    name: string
    kind: "watch" | "phone" | "app" | "manual"
    bundleId?: string
    device?: string
    priority: number
    lastSeenAt: number
    createdAt: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/me/health/sharing

Your sharing: rules per category and metric, the rule in force for every metric, Sexual Activity's own sharing, and how many people follow you and you follow on Mirage.

Auth: user access token or platform agent key

Response 200

{
  settings: {
    scope: "category" | "metric"
    id: string
    rule: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    updatedAt: number
  }[]
  effective: {
    [key: string]: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
  }
  sexualShare: {
    audience: "public" | "following" | "followers" | "only_me" | "friends"
    counts: boolean
    protectionRate: boolean
    partnerCount: boolean
    confirmedAt?: number
  }
  audiences: {
    onSocial: boolean
    followers: number
    following: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

PUT /v1/me/health/sharing/:scope/:id

Shares a metric or category (audience: only_me, friends (mutual follows), followers, following or public; detail: aggregates or samples). Sensitive categories share aggregates only; Sexual Activity only through its own settings. In the app only.

Auth: user access token or platform agent key

Path parameterDescription
:scopemetrics (one metric's rule) or categories (a category's rule, which its metrics follow unless they have their own).
:idA record's id in Customers: its object's prefix and a time-sortable id (acc_…, cnt_…, led_…, opp_…, act_…).

Request body

FieldTypeRequiredDefaultNotes
audience"only_me" | "friends" | "followers" | "following" | "public"Yes
detail"aggregates" | "samples"No"aggregates"

Also checked: Unknown fields are rejected.

Response 200

{
  settings: {
    scope: "category" | "metric"
    id: string
    rule: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    updatedAt: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

DELETE /v1/me/health/sharing/:scope/:id

Removes a metric's or category's own rule (a metric then follows its category; a category goes back to Only Me). In the app only.

Auth: user access token or platform agent key

Path parameterDescription
:scopemetrics (one metric's rule) or categories (a category's rule, which its metrics follow unless they have their own).
:idA record's id in Customers: its object's prefix and a time-sortable id (acc_…, cnt_…, led_…, opp_…, act_…).

Response 200

{
  settings: {
    scope: "category" | "metric"
    id: string
    rule: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    updatedAt: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

PUT /v1/me/health/sexual/sharing

Sexual Activity's own sharing, separate from everything else: an audience and which aggregates (counts, protectionRate, partnerCount), with confirm: true whenever anything is shared. Never names or dates of entries; viewers must be 18 or over. In the app only.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
audience"only_me" | "friends" | "followers" | "following" | "public"Yes
countsbooleanYes
protectionRatebooleanYes
partnerCountbooleanYes
confirmtrueNo

Also checked: Unknown fields are rejected.

Response 200

{
  profile: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/me/health/sharing/preview

How a viewer in an audience sees the person's shared Health (nothing is recorded).

Auth: user access token or platform agent key

Query parameterTypeRequiredNotes
as"friends" | "followers" | "following" | "public" | "stranger"Yes

Response 200

{
  userId: string
  metrics: {
    metricId: string
    detail: "samples" | "aggregates"
    today: null | number
    days: {
      day: string
      value: null | number
    }[]
    streak: number
    longestStreak: number
    best: null | {
      day: string
      value: number
    }
    average: null | number
    samples?: {
      value: number
      start: number
      stage?: number
      end: number
      sampleId: string
    }[]
  }[]
  sexual: null | {
    counts?: {
      week: number
      month: number
      year: number
      all: number
    }
    protectionRate?: null | number
    partnerCount?: number
  }
  defs: {
    metricId: string
    label: string
    category: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    kind: "duration" | "event" | "category" | "quantity"
    unit: string
    units: {
      id: string
      label: string
      factor: number
      offset?: number
    }[]
    aggregation: "duration" | "count" | "sum" | "average" | "latest"
    decimals: number
    sensitivity: "standard" | "sensitive" | "sexual"
    values?: {
      value: number
      label: string
    }[]
    healthKit?: {
      identifier: string
      kind: "category" | "quantity" | "workout"
      unit?: string
      readOnly?: boolean
      factor?: number
      categoryValues?: number[]
    }
    healthConnect?: string
    leaderboard?: "count" | "sum" | "average"
    min?: number
    max?: number
    pinned?: boolean
    description?: string
    enabled: boolean
    sortOrder: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/sexual/summary

Your Sexual Activity counts (this week, month, year and all time), the protection-used rate, and how many different partners your entries name. 404 unless the category is on.

Auth: user access token or platform agent key

Response 200

{
  counts: {
    week: number
    month: number
    year: number
    all: number
  }
  protectionRate: null | number
  partnerCount: number
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.
404Sexual Activity isn't on.

GET /v1/me/health/leaderboards

Your leaderboard opt-ins (server and metric) and the Mirage servers you're in, each with its leaderboards as GET /v1/health/servers/:serverId returns them (health; null when they couldn't be read).

Auth: user access token or platform agent key

Response 200

{
  optIns: {
    serverId: string
    metricId: string
    at: number
  }[]
  servers: {
    health: null
    serverId: string
    name: string
    iconUrl: null | string
  } | {
    health: {
      settings: {
        metrics: string[]
        allowSexual: boolean
        enabled: boolean
        updatedAt: null | number
        updatedBy: null | string
      }
      canManage: boolean
      available: string[]
      defs: {
        metricId: string
        label: string
        category: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
        kind: "duration" | "event" | "category" | "quantity"
        unit: string
        units: object[]
        aggregation: "duration" | "count" | "sum" | "average" | "latest"
        decimals: number
        sensitivity: "standard" | "sensitive" | "sexual"
        values?: object[]
        healthKit?: {
          identifier: string
          kind: "category" | "quantity" | "workout"
          unit?: string
          readOnly?: boolean
          factor?: number
          categoryValues?: object
        }
        healthConnect?: string
        leaderboard?: "count" | "sum" | "average"
        min?: number
        max?: number
        pinned?: boolean
        description?: string
        enabled: boolean
        sortOrder: number
      }[]
      adult: boolean
      optedIn: string[]
    }
    serverId: string
    name: string
    iconUrl: null | string
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/me/health/audit

Your Health audit, newest first: consents, sharing changes, leaderboard opt-ins, Caity's reads, exports, and who viewed what you share (once a day each). In the app only.

Auth: user access token or platform agent key

Query parameterTypeRequiredNotes
cursorstringNoup to 2,000 characters

Response 200

{
  entries: {
    id: string
    at: number
    action: "export" | "consent.accept" | "consent.withdraw" | "consent.sensitive" | "share.update" | "share.sexual" | "share.view" | "leaderboard.opt_in" | "leaderboard.opt_out" | "assistant.update" | "assistant.read" | "api.update" | "delete_all" | "device.add" | "device.remove"
    text: string
    actor: null | {
      userId: string
      name?: string
    }
    details?: {
      [key: string]: unknown
    }
  }[]
  cursor: null | string
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/me/health/export

Your data, a page at a time (cursor from the last page): the first page also has your profile, sources, sharing and metric states; partners included.

Auth: user access token or platform agent key

Query parameterTypeRequiredNotes
cursorstringNoup to 2,000 characters

Response 200

{
  samples: {
    sampleId: string
    metricId: string
    start: number
    end: number
    value: number
    stage?: number
    protection?: boolean | null
    partner?: {
      name?: string
      userId?: string
    }
    note?: string
    meta?: {
      [key: string]: boolean | string | number
    }
    sourceId: string
    sourceName: string
    external: boolean
    version: number
    createdAt: number
    updatedAt: number
  }[]
  cursor: null | string
  profile?: {
    userId: string
    consent: null | {
      version: number
      at: number
    }
    sensitiveConsent: {
      body?: number
      heart?: number
      other?: number
      activity?: number
      cycle?: number
      hearing?: number
      medications?: number
      mental?: number
      mindfulness?: number
      mobility?: number
      nutrition?: number
      respiratory?: number
      sleep?: number
      symptoms?: number
      vitals?: number
      sexual?: number
    }
    timeZone: string
    pinned: string[]
    assistant: {
      enabled: boolean
      categories: ("body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual")[]
    }
    sexualShare: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      counts: boolean
      protectionRate: boolean
      partnerCount: boolean
      confirmedAt?: number
    }
    apiAccess: boolean
    adult: boolean
    ageUnknown: boolean
    createdAt: number
    updatedAt: number
  }
  sources?: {
    sourceId: string
    name: string
    kind: "watch" | "phone" | "app" | "manual"
    bundleId?: string
    device?: string
    priority: number
    lastSeenAt: number
    createdAt: number
  }[]
  sharing?: {
    scope: "category" | "metric"
    id: string
    rule: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    updatedAt: number
  }[]
  metrics?: {
    metricId: string
    unit?: string
    share?: {
      audience: "public" | "following" | "followers" | "only_me" | "friends"
      detail: "samples" | "aggregates"
    }
    count: number
    firstAt?: number
    lastAt?: number
    months: string[]
    updatedAt: number
  }[]
  exportedAt: number
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

POST /v1/me/health/delete-all

Deletes everything; call again while done is false.

Auth: user access token or platform agent key

Request body

FieldTypeRequiredNotes
confirm"delete"Yes

Also checked: Unknown fields are rejected.

Response 200

{
  done: boolean
  remaining: number
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/health/people/:userId

What someone shares with you: each metric's last 30 days, today, streaks and best day (samples only where they chose), and Sexual Activity's aggregates they opted in, when you're both 18 or over. Empty when you're in none of their audiences. Your view is in their audit once a day.

Auth: user access token or platform agent key

Path parameterDescription
:userIdA member's user id (usr_…).

Response 200

{
  userId: string
  metrics: {
    metricId: string
    detail: "samples" | "aggregates"
    today: null | number
    days: {
      day: string
      value: null | number
    }[]
    streak: number
    longestStreak: number
    best: null | {
      day: string
      value: number
    }
    average: null | number
    samples?: {
      value: number
      start: number
      stage?: number
      end: number
      sampleId: string
    }[]
  }[]
  sexual: null | {
    counts?: {
      week: number
      month: number
      year: number
      all: number
    }
    protectionRate?: null | number
    partnerCount?: number
  }
  defs: {
    metricId: string
    label: string
    category: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    kind: "duration" | "event" | "category" | "quantity"
    unit: string
    units: {
      id: string
      label: string
      factor: number
      offset?: number
    }[]
    aggregation: "duration" | "count" | "sum" | "average" | "latest"
    decimals: number
    sensitivity: "standard" | "sensitive" | "sexual"
    values?: {
      value: number
      label: string
    }[]
    healthKit?: {
      identifier: string
      kind: "category" | "quantity" | "workout"
      unit?: string
      readOnly?: boolean
      factor?: number
      categoryValues?: number[]
    }
    healthConnect?: string
    leaderboard?: "count" | "sum" | "average"
    min?: number
    max?: number
    pinned?: boolean
    description?: string
    enabled: boolean
    sortOrder: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

GET /v1/health/servers/:serverId

A Mirage server's Health leaderboards for a member: the settings, the metrics that can rank, whether you can manage them, whether you're known to be 18 or over (adult; Sexual Activity's leaderboard shows only then), and the metrics you opted in there.

Auth: user access token or platform agent key

Path parameterDescription
:serverIdMirage server id (gld_…).

Response 200

{
  settings: {
    metrics: string[]
    allowSexual: boolean
    enabled: boolean
    updatedAt: null | number
    updatedBy: null | string
  }
  canManage: boolean
  available: string[]
  defs: {
    metricId: string
    label: string
    category: "body" | "heart" | "other" | "activity" | "cycle" | "hearing" | "medications" | "mental" | "mindfulness" | "mobility" | "nutrition" | "respiratory" | "sleep" | "symptoms" | "vitals" | "sexual"
    kind: "duration" | "event" | "category" | "quantity"
    unit: string
    units: {
      id: string
      label: string
      factor: number
      offset?: number
    }[]
    aggregation: "duration" | "count" | "sum" | "average" | "latest"
    decimals: number
    sensitivity: "standard" | "sensitive" | "sexual"
    values?: {
      value: number
      label: string
    }[]
    healthKit?: {
      identifier: string
      kind: "category" | "quantity" | "workout"
      unit?: string
      readOnly?: boolean
      factor?: number
      categoryValues?: number[]
    }
    healthConnect?: string
    leaderboard?: "count" | "sum" | "average"
    min?: number
    max?: number
    pinned?: boolean
    description?: string
    enabled: boolean
    sortOrder: number
  }[]
  adult: boolean
  optedIn: string[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.

PUT /v1/health/servers/:serverId/settings

Turns a server's Health leaderboards on or off and picks metrics (enabled, metrics). allowSexual is the Sexual Activity leaderboard's own switch (off by default; only a manager known to be 18 or over changes it); turning it off takes everyone off it. Manage Server.

Auth: user access token or platform agent key

Path parameterDescription
:serverIdMirage server id (gld_…).

Request body

FieldTypeRequiredDefaultNotes
enabledbooleanYes
metricsstring[]Yesup to 20 items; each up to 48 characters
allowSexualbooleanNofalse

Also checked: Unknown fields are rejected.

Response 200

{
  settings: {
    enabled: boolean
    metrics: string[]
    allowSexual: boolean
    updatedAt: null | number
    updatedBy: null | string
  }
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

PUT /v1/health/servers/:serverId/opt-ins/:metricId

Ranks you with a metric on this server's leaderboards (it must be one the server chose); your scores are written at once.

Auth: user access token or platform agent key

Path parameterDescription
:serverIdMirage server id (gld_…).
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.

Response 200

{
  optIns: {
    serverId: string
    metricId: string
    at: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

DELETE /v1/health/servers/:serverId/opt-ins/:metricId

Stops ranking: your opt-in and every score for that server and metric go.

Auth: user access token or platform agent key

Path parameterDescription
:serverIdMirage server id (gld_…).
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.

Response 200

{
  optIns: {
    serverId: string
    metricId: string
    at: number
  }[]
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:write on a personal key whose owner allowed it.
403Change Health's privacy settings in the app.

GET /v1/health/servers/:serverId/leaderboards/:metricId

A server's board (period week, month or all; at a past period such as w2026-10-05 or m2026-10): members who opted in, ranked, up to 100. Members only. Sexual Activity's ranks entries by the week only, among adults, and only for viewers known to be 18 or over.

Auth: user access token or platform agent key

Path parameterDescription
:serverIdMirage server id (gld_…).
:metricIdA Health metric's id from the registry (steps, heart_rate, sleep, sexual_activity, …), as GET /v1/me/health/metrics lists them.
Query parameterTypeRequiredDefaultNotes
period"week" | "month" | "all"No"week"
atstringNoup to 16 characters

Response 200

{
  serverId: string
  metricId: string
  period: "all" | "month" | "week"
  periodKey: string
  entries: {
    rank: number
    userId: string
    name: string
    avatarUrl: null | string
    value: number
    you: boolean
  }[]
  optedIn: boolean
}

Errors

StatusMessage
403Health is only reachable from the Health, phone and Mirage apps.
403Its owner hasn't let API keys use Health (Health → Privacy).
403Health needs health:read on a personal key whose owner allowed it.