AnpherosAnpheros PlatformDevelopers

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no cardYour first API call in 2 minutes →

Polar AccessLink API to FHIR: sleep, heart rate and steps (with code)

Read Polar AccessLink v3 sleep, heart rate and steps and store them as FHIR R4 Observations, with user registration, rate limits and phone sync.

The Polar AccessLink API v3 gives your app a person's daily activity and steps, continuous heart rate, sleep, Nightly Recharge, exercises and biosensing data such as SpO₂ and skin temperature after they approve your OAuth client. Anyone with a Polar Flow account can register a client under Polar's AccessLink licence agreement. You can store each reading as a LOINC-coded FHIR R4 Observation with one standard API call. Anpheros does not connect to Polar's cloud itself: your code reads Polar, and Anpheros keeps the record with the person's consent. On phones, Polar Flow writes sleep, steps and workouts to Apple Health, and heart rate, SpO₂, sleep stages and steps to Health Connect.

Read Polar data and store it in FHIR

First, the person's daily activity from Polar AccessLink (an access token from your AccessLink client with the accesslink.read_all scope, after you have registered the person with POST /v3/users):

curl -X GET https://www.polaraccesslink.com/v3/users/activities \
  -H 'Accept: application/json' \
  -H "Authorization: Bearer $POLAR_TOKEN"

Then the day's steps as a FHIR Observation in the person's record (sandbox key sk_test_…):

curl -X POST https://platform.anpheros.com/fhir/R4/Observation \
  -H "Authorization: Bearer $ANPHEROS_KEY" \
  -H "Content-Type: application/fhir+json" \
  -H "X-Anpheros-Author-Type: device" \
  -d '{"resourceType":"Observation","status":"final",
       "category":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/observation-category","code":"activity"}]}],
       "code":{"coding":[{"system":"http://loinc.org","code":"41950-7","display":"Number of steps in 24 hour Measured"}]},
       "subject":{"reference":"Patient/<id>"},
       "effectivePeriod":{"start":"2026-11-02T00:00:00+01:00","end":"2026-11-02T23:59:59+01:00"},
       "valueQuantity":{"value":9640,"unit":"{steps}","system":"http://unitsofmeasure.org","code":"{steps}"},
       "device":{"display":"Polar watch (Polar Flow)"}}'

The same in Python: every night of sleep becomes one Observation, sent together in one transaction Bundle.

import os, requests

FHIR = "https://platform.anpheros.com/fhir/R4"
fhir = {"Authorization": f"Bearer {os.environ['ANPHEROS_KEY']}", "Content-Type": "application/fhir+json",
        "X-Anpheros-Author-Type": "device"}

# Nights your backend already read from GET /v3/users/sleep; map Polar's fields
# (listed in the AccessLink reference) to start, end and minutes asleep.
sleep_by_night = [
    {"start": "2026-11-01T23:15:00+01:00", "end": "2026-11-02T06:58:00+01:00", "minutes": 432},
    {"start": "2026-11-02T23:40:00+01:00", "end": "2026-11-03T07:05:00+01:00", "minutes": 409},
]

entries = [{
    "request": {"method": "POST", "url": "Observation"},
    "resource": {
        "resourceType": "Observation", "status": "final",
        "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "activity"}]}],
        "code": {"coding": [{"system": "http://loinc.org", "code": "93832-4", "display": "Sleep duration"}]},
        "subject": {"reference": "Patient/<id>"},
        "effectivePeriod": {"start": n["start"], "end": n["end"]},
        "valueQuantity": {"value": n["minutes"], "unit": "min", "system": "http://unitsofmeasure.org", "code": "min"},
        "device": {"display": "Polar watch (Polar Flow)"},
    },
} for n in sleep_by_night]

r = requests.post(FHIR, headers=fhir, json={"resourceType": "Bundle", "type": "transaction", "entry": entries})
print(r.status_code, len(entries), "nights saved")

And in JavaScript (Node 18+), one day's heart rate summarised from continuous heart rate:

const fhir = { Authorization: `Bearer ${process.env.ANPHEROS_KEY}`, 'Content-Type': 'application/fhir+json' };

// From GET /v3/users/continuous-heart-rate/{date}: your code works out the day's average, minimum and maximum.
const heartRateForDay = { day: '2026-11-02', avg: 66, min: 47, max: 152 };
const bpm = (value) => ({ value, unit: '/min', system: 'http://unitsofmeasure.org', code: '/min' });

await fetch('https://platform.anpheros.com/fhir/R4/Observation', {
  method: 'POST', headers: fhir,
  body: JSON.stringify({
    resourceType: 'Observation', status: 'final',
    category: [{ coding: [{ system: 'http://terminology.hl7.org/CodeSystem/observation-category', code: 'vital-signs' }] }],
    code: { coding: [{ system: 'http://loinc.org', code: '8867-4', display: 'Heart rate' }] },
    subject: { reference: 'Patient/<id>' },
    effectivePeriod: { start: `${heartRateForDay.day}T00:00:00+01:00`, end: `${heartRateForDay.day}T23:59:59+01:00` },
    valueQuantity: bpm(heartRateForDay.avg),
    component: [
      { code: { text: 'minimum' }, valueQuantity: bpm(heartRateForDay.min) },
      { code: { text: 'maximum' }, valueQuantity: bpm(heartRateForDay.max) },
    ],
    device: { display: 'Polar watch (Polar Flow)' },
  }),
});

Polar's response field names are in the AccessLink reference, so the examples start from values your code has already read. The Anpheros side is standard FHIR R4, so the same requests work with any FHIR server. To avoid copies when a day is read again, give each Observation a stable identifier, as shown in Wearable data in FHIR.

Ways to get Polar data into FHIR

Path Status What you need
Your backend reads the Polar AccessLink API, then writes FHIR to Anpheros Works today An AccessLink client (Polar Flow account, licence agreement) and the person's consent to all mandatory consents
Polar Flow → Apple Health → your iPhone app reads HealthKit → Anpheros Works today HealthKit permissions. One way: sleep, steps, workouts, workout heart rate, weight; no continuous heart rate. See Apple Health to FHIR
Polar Flow → Health Connect → your Android app → Anpheros Works today Health Connect permissions. Includes heart rate, resting heart rate, SpO₂, sleep stages and steps. See Health Connect to FHIR
A direct Polar connector inside Anpheros On our roadmap Not available yet. Use the button below to tell us you need it

The Polar AccessLink API in short

Access. Register a client at admin.polaraccesslink.com with a Polar Flow account; use is governed by the AccessLink Limited License Agreement. Polar does not state a price. Each person must accept every mandatory consent, or the API answers 403. You only get data that reached Polar Flow after the person registered with your client, so there is no backfill of older history.

Auth. OAuth 2.0 authorization code flow. Send the person to https://flow.polar.com/oauth2/authorization?response_type=code&client_id=…, then exchange the code at POST https://polarremote.com/v2/oauth2/token. The code is valid for 10 minutes and works once. The scope is accesslink.read_all. After authorization, register the person with POST /v3/users (the body includes a member-id).

Data Endpoint (GET, base https://www.polaraccesslink.com) Fields
Sleep /v3/users/sleep, /v3/users/sleep/{date}, /v3/users/sleep/available nights of sleep
Nightly Recharge (ANS, HRV) /v3/users/nightly-recharge, /v3/users/nightly-recharge/{date} overnight recovery
Heart rate /v3/users/continuous-heart-rate/{date}, /v3/users/continuous-heart-rate?from=&to= continuous samples
Steps and activity /v3/users/activities, /v3/users/activities/{date}, /v3/users/activities/samples daily activity, samples
SpO₂ and biosensing /v3/users/biosensing/spo2, /ecg, /skintemperature, /bodytemperature Elixir biosensing data
Also /v3/exercises (with FIT, TCX, GPX), /v3/users/cardio-load, /v3/users/physical-info

Rate limits grow with your user count: in each 15-minute window, 500 + 20 × users requests; in each 24 hours, 5,000 + 100 × users. A 429 comes with RateLimit-Usage, RateLimit-Limit and RateLimit-Reset headers. Webhooks live under /v3/webhooks (create, activate, deactivate, update, delete), and GET /v3/notifications offers pull notifications with client credentials. Polar has deprecated the transaction-based physical info, daily activity and exercise resources in favour of the non-transactional ones above; the AccessLink changelog runs to January 2026.

Sources: Polar AccessLink API v3 documentation, Polar Flow and Apple Health, Polar Flow and Health Connect, November 2026.

Polar data as FHIR Observations

Polar data LOINC UCUM unit Note
Sleep duration 93832-4 min one per night
Steps (daily activity) 41950-7 {steps} one per day
Heart rate (continuous) 8867-4 /min daily average, with minimum and maximum as components rather than every sample
SpO₂ (biosensing) 59408-5 %
Body temperature (biosensing) 8310-5 Cel skin temperature is a different measurement; give it its own code
Body weight (physical info) 29463-7 kg
HRV (Nightly Recharge) see note ms check which statistic Polar reports; do not file it under LOINC 80404-7 unless it is SDNN. See Wearable data in FHIR
Nightly Recharge, cardio load none Polar scores with no LOINC code; keep them under your own code system or leave them out

Frequently asked questions

Is the Polar AccessLink API free?

Polar does not state a price. You register a client with a Polar Flow account and accept the AccessLink Limited License Agreement.

How do I get access to the Polar AccessLink API?

Register a client at admin.polaraccesslink.com, send people through the OAuth flow, then register each one with POST /v3/users before you read their data.

What is the Polar AccessLink rate limit?

It scales with your users: 500 + 20 × users requests per 15 minutes and 5,000 + 100 × users per 24 hours. Watch the RateLimit-* headers.

Why does Polar AccessLink return 403?

Polar documents one cause: the person has not accepted all the mandatory consents. Each end user must accept them before their data comes through.

Can I read Polar data from before the person connected?

No. AccessLink returns only data uploaded to Polar Flow after the person registered with your client.

Does Anpheros connect to Polar directly?

Not yet. Today your code reads the Polar AccessLink API (or HealthKit / Health Connect on the phone) and writes standard FHIR to Anpheros. A direct Polar connector is on our roadmap; tell us with the button on this page if you need it.

Related

Ask your AI

Paste this into Claude, ChatGPT, Cursor or Claude Code. Your assistant reads this guide and adapts it to your code.

Read https://developers.anpheros.com/guides/polar-api.md and help me apply this guide to my own project. Use the Anpheros sandbox (base URL https://platform.anpheros.com) with my API key from the ANPHEROS_KEY environment variable, never written in the code. Give me complete, runnable code, the response I should expect, and how to fix the errors in https://developers.anpheros.com/guides/troubleshooting.md if a call fails.

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no cardYour first API call in 2 minutes →

Product updates by email

New features, guides and the end of the beta. One email a month at most.

Send me occasional Anpheros Platform updates by email (new features, API changes, guides). I'll confirm by email and can unsubscribe in one click from any email. Privacy