# Dexcom API to FHIR: get CGM glucose readings into your app (with code)

> Read CGM glucose from the Dexcom API v3 and store each reading as a FHIR Observation: access tiers, OAuth, endpoints, limits and the US partner pause.

Source: https://developers.anpheros.com/guides/dexcom-api

**The Dexcom API v3 gives your app a person's CGM glucose readings (estimated glucose values, EGVs), events, alerts and device details after they sign in with Dexcom and approve your OAuth app. You can store each reading as a LOINC-coded FHIR R4 Observation with one standard API call. Anpheros does not connect to Dexcom's cloud itself: your code reads Dexcom (or the phone's health store), and Anpheros keeps the record with the person's consent. The Dexcom sandbox is self-service; real users need Limited Access (up to 5 users) or Full Access, both reviewed by Dexcom, and Dexcom is currently not reviewing new US partner applications, except for Stelo. On phones, the Dexcom app can also share glucose with Apple Health and Health Connect, with a 3-hour delay.**

## Read Dexcom glucose and store it in FHIR (5 minutes)

First, a day of glucose readings from Dexcom (an access token from your Dexcom OAuth app; use `https://sandbox-api.dexcom.com` while you test, `https://api.dexcom.eu` for users outside the US):

```bash
curl -H "Authorization: Bearer $DEXCOM_TOKEN" \
     "https://api.dexcom.com/v3/users/self/egvs?startDate=2026-11-02T00:00:00&endDate=2026-11-03T00:00:00"
```

Then one reading as a FHIR Observation in the person's record (sandbox key `sk_test_…`):

```bash
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":"vital-signs"}]}],
       "code":{"coding":[{"system":"http://loinc.org","code":"2339-0","display":"Glucose [Mass/volume] in Blood"}]},
       "subject":{"reference":"Patient/<id>"},
       "effectiveDateTime":"2026-11-02T08:15:00Z",
       "valueQuantity":{"value":112,"unit":"mg/dL","system":"http://unitsofmeasure.org","code":"mg/dL"},
       "device":{"display":"Dexcom G7"},
       "note":[{"text":"CGM estimated glucose value (interstitial), from the Dexcom API v3"}]}'
```

The same in Python: every EGV becomes one Observation, sent together in one transaction Bundle. The `recordId` goes into an identifier, so the same reading is not stored twice when you sync again.

```python
import os, requests

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

r = requests.get(f"{DEXCOM}/egvs", headers=dexcom,
                 params={"startDate": "2026-11-02T00:00:00", "endDate": "2026-11-03T00:00:00"})
egvs = r.json()["records"]

def utc(t):  # Dexcom's systemTime is UTC; FHIR needs the offset written out
    return t if t.endswith("Z") or "+" in t[10:] else t + "Z"

entries = [{
    "request": {"method": "POST", "url": "Observation"},
    "resource": {
        "resourceType": "Observation", "status": "final",
        "identifier": [{"system": "https://yourapp.example/dexcom-egv", "value": e["recordId"]}],
        "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs"}]}],
        "code": {"coding": [{"system": "http://loinc.org", "code": "2339-0", "display": "Glucose [Mass/volume] in Blood"}]},
        "subject": {"reference": "Patient/<id>"},
        "effectiveDateTime": utc(e["systemTime"]),
        "valueQuantity": {"value": e["value"], "unit": "mg/dL", "system": "http://unitsofmeasure.org", "code": "mg/dL"},
        "device": {"display": e.get("displayDevice") or "Dexcom CGM"},
        "note": [{"text": "CGM estimated glucose value (interstitial)"}],
    },
} for e in egvs if e.get("value") is not None]

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

And in JavaScript (Node 18+), the newest reading only:

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

const { records } = await (await fetch(
  'https://api.dexcom.com/v3/users/self/egvs?startDate=2026-11-02T00:00:00&endDate=2026-11-03T00:00:00',
  { headers: dexcom })).json();
const last = records.filter((e) => e.value != null).sort((a, b) => a.systemTime.localeCompare(b.systemTime)).pop();

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: '2339-0', display: 'Glucose [Mass/volume] in Blood' }] },
    subject: { reference: 'Patient/<id>' },
    effectiveDateTime: last.systemTime.endsWith('Z') ? last.systemTime : `${last.systemTime}Z`,
    valueQuantity: { value: last.value, unit: 'mg/dL', system: 'http://unitsofmeasure.org', code: 'mg/dL' },
    device: { display: last.displayDevice ?? 'Dexcom CGM' },
    note: [{ text: 'CGM estimated glucose value (interstitial)' }],
  }),
});
```

Field names (`recordId`, `systemTime`, `value`, `unit`, `displayDevice`) are from Dexcom's v3 EGV reference. The Anpheros side is standard FHIR R4, so the same requests work with any FHIR server. Anpheros stores the readings as they come: it does not interpret glucose values, raise alerts or give treatment advice.

## Ways to get Dexcom data into FHIR

| Path | Status | What you need |
|---|---|---|
| Your backend reads the Dexcom API v3, then writes FHIR to Anpheros | **Works today** | A Dexcom developer account (sandbox is self-service). Real users need Limited Access (up to 5 users) or Full Access, both reviewed by Dexcom. New US partner applications are paused, except for Stelo; requests from outside the US are reviewed |
| Dexcom app → Apple Health → your iPhone app reads HealthKit → Anpheros | **Works today** | The person turns on Apple Health in the Dexcom app; glucose arrives with a 3-hour delay. See [Apple HealthKit to FHIR](https://developers.anpheros.com/guides/apple-health-fhir) |
| Dexcom app → Health Connect → your Android app → Anpheros | **Works today** | Health Connect permissions; data arrives with a 3-hour delay. See [Health Connect to FHIR](https://developers.anpheros.com/guides/health-connect-fhir) |
| A direct Dexcom connector inside Anpheros | **On our roadmap** | Not available yet. Use the button below to tell us you need it |

<!-- visual:cta-wear-dexcom -->

## The Dexcom API in short

**Access.** Registration on Dexcom's developer portal is free, and the sandbox, with simulated users, needs no approval (including a `G715DAY` user for the G7 15-day sensor). For real users you apply for an upgrade: **Limited Access** allows up to 5 users per app and comes with a standard Data Licensing Agreement; **Full Access** adds a questionnaire and a technical and commercial review, for each app. Dexcom may decline a request. At the time of writing, Dexcom is not reviewing new US partner applications (Stelo excepted) and is reviewing requests from outside the US; it gives no date for the US pause. Separate real-time partner APIs exist for partners Dexcom invites.

**Auth.** OAuth 2.0 authorization code flow. Send the person to `{base}/v3/oauth2/login` with `client_id`, `redirect_uri`, `response_type=code`, `scope=offline_access` and `state`, then exchange the code at `POST {base}/v3/oauth2/token` (form-encoded, with your client ID and secret). The code expires after 1 minute, access tokens after 2 hours, and refresh tokens are single use: each refresh returns a new one, valid for at most a year. `offline_access` is the only scope.

| Data | Endpoint (GET, base `https://api.dexcom.com`) | What you get |
|---|---|---|
| Glucose readings | `/v3/users/self/egvs` | `recordId`, `systemTime`, `displayTime`, `value`, `status`, `trend`, `trendRate`, `unit`, `transmitterGeneration`, `displayDevice` |
| Events | `/v3/users/self/events` | entries the person logs: carbs, insulin, exercise, health, blood glucose (empty for Dexcom ONE) |
| Alerts | `/v3/users/self/alerts` | alert records |
| Devices | `/v3/users/self/devices` | the person's Dexcom devices |
| Calibrations | `/v3/users/self/calibrations` | calibration records |
| Available range | `/v3/users/self/dataRange` | the date range of the person's data |

Other hosts: `https://sandbox-api.dexcom.com` (sandbox), `https://api.dexcom.eu` (EU and outside the US), `https://api.dexcom.jp` (Japan). Every endpoint except `dataRange` needs `startDate` and `endDate`, in ISO 8601 UTC, matched against `systemTime`: the start is included, the end is not, and a window longer than 30 days returns 400. Values are in mg/dL and TLS 1.3 is required. Readings uploaded from the mobile app appear after about 1 hour in the US and 3 hours elsewhere; receiver uploads over USB appear at once. The limit is 60,000 calls per app per hour, with 429 above it. Supported sensors: G6, G7, G7 15-day, Dexcom ONE and ONE+. The API carries glucose data only: no sleep, heart rate or steps.

Sources: [Dexcom scopes and access](https://developer.dexcom.com/docs/dexcom/scopes-access), [authentication](https://developer.dexcom.com/docs/dexcom/authentication), [v3 endpoint overview](https://developer.dexcom.com/docs/dexcomv3/endpoint-overview), [EGV reference](https://developer.dexcom.com/docs/swaggerv3/other/getestimatedglucosevaluesv3), [partner intake requests](https://www.dexcom.com/en-us/global-partner-intake-requests), [sharing with Apple Health](https://www.dexcom.com/en-us/faqs/how-do-i-share-my-glucose-data-with-the-apple-health-app), November 2026.

## Dexcom data as FHIR Observations

| Dexcom data | FHIR | Note |
|---|---|---|
| Glucose reading (`value`, mg/dL) | `valueQuantity`, LOINC 2339-0, UCUM `mg/dL`, category vital-signs | 2339-0 is the blood glucose code used on [Wearable data in FHIR](https://developers.anpheros.com/guides/wearable-data-fhir). CGM readings are interstitial: say so in a `note` and record the sensor in `device` |
| `systemTime` (UTC) | `effectiveDateTime` | add the `Z`; `displayTime` is the time shown on the person's device |
| `recordId` | `identifier` | stops duplicates when you sync the same window again |
| `displayDevice`, `transmitterGeneration` | `device.display` | for example "Dexcom G7" |
| `trend`, `trendRate` | leave out, or a component with your own code | no LOINC code in our table |
| Events, alerts, calibrations | not covered here | store them only if your app needs them, with codes you document |

Store glucose in one unit. Dexcom returns mg/dL; if other sources give mmol/L, convert them or keep them under their own unit, but never mix units under one code.

## Frequently asked questions

### Does Dexcom have a public API?
Yes. The Dexcom API v3 is a documented REST API with OAuth 2.0. The sandbox is free and self-service; reading real users needs Limited Access (up to 5 users) or Full Access, both reviewed by Dexcom.

### Is Dexcom accepting new developers in the US?
Dexcom says it is not reviewing new US partner applications for now, except for Stelo, and is reviewing requests from outside the US. You can still build and test against the sandbox.

### Is Dexcom API data real time?
No. Readings uploaded from the Dexcom mobile app appear in the API after about 1 hour in the US and about 3 hours elsewhere. Dexcom's real-time partner APIs are only for partners it invites.

### How much data can I request at once?
Up to 30 days per request; a longer window returns 400. Each app can make 60,000 calls per hour.

### Does Dexcom sync with Apple Health and Health Connect?
Yes. The Dexcom app can share glucose with Apple Health and with Health Connect, with a 3-hour delay. Your phone app can then read it there, with the person's permission.

### Does Anpheros connect to Dexcom directly?
Not yet. Today your code reads the Dexcom API (or HealthKit / Health Connect on the phone) and writes standard FHIR to Anpheros. A direct Dexcom connector is on our roadmap; tell us with the button on this page if you need it. Anpheros stores the readings and does not interpret them or give dosing advice.

## Related

- [Wearable APIs: every brand compared](https://developers.anpheros.com/guides/wearable-apis)
- [FreeStyle Libre API: get Libre glucose data into FHIR](https://developers.anpheros.com/guides/freestyle-libre-api)
- [Wearable data in FHIR (Apple Health, Health Connect)](https://developers.anpheros.com/guides/wearable-data-fhir)
- [Apple HealthKit to FHIR](https://developers.anpheros.com/guides/apple-health-fhir) · [Health Connect to FHIR](https://developers.anpheros.com/guides/health-connect-fhir)
- [Oura API to FHIR](https://developers.anpheros.com/guides/oura-api) · [Garmin API to FHIR](https://developers.anpheros.com/guides/garmin-api) · [Google Health API](https://developers.anpheros.com/guides/google-health-api)
- [Remote patient monitoring with FHIR](https://developers.anpheros.com/guides/remote-patient-monitoring-fhir)
