> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/reference/health-and-fitness-api/sdk-references/flutter.md).

# Flutter

## Connections

| Value                      | Platform | Description                                                               |
| -------------------------- | -------- | ------------------------------------------------------------------------- |
| `Connection.appleHealth`   | iOS      | Apple Health (HealthKit)                                                  |
| `Connection.samsung`       | Android  | Samsung Health, read via Health Connect (filtered to Samsung Health data) |
| `Connection.healthConnect` | Android  | Health Connect (reads all data sources)                                   |
| `Connection.googleFit`     | Android  | Google Fit (via Health Connect, filtered to Google Fit data)              |

{% hint style="warning" %}
Passing an iOS-only connection on Android (or vice versa) will result in a `PlatformException`. The SDK does not guard against this at the Dart level.
{% endhint %}

## CustomPermission

Use these to request a subset of permissions. When not specified, all permissions from your developer scopes are requested. See `lib/models/enums.dart` for the exact value names. The tables below show what each value requests on each platform; see [Permissions mapping](/reference/health-and-fitness-api/sdk-references/permissions-mapping.md) for the full reference.

Notable enum gaps specific to the Flutter SDK: `menstruation` and `electrocardiogram` are recognized on iOS but **silently ignored** on Android. `mindfulness` is recognized on both native platforms but has **no Dart enum value**.

{% tabs %}
{% tab title="Apple Health" %}
Each `CustomPermissions` value maps to one or more HealthKit types. When you don't pass `customPermissions`, the SDK requests **every** type associated with the data-type groups in your developer scopes — so the HealthKit prompt can show a long list. Pass `customPermissions` to request a narrower set.

## Activity & workouts

| `CustomPermissions` value | HealthKit type(s) requested                                                 |
| ------------------------- | --------------------------------------------------------------------------- |
| `WORKOUT_TYPE`            | Workouts                                                                    |
| `ACTIVITY_SUMMARY`        | Activity summary, Stand time, Exercise time                                 |
| `ACTIVE_DURATIONS`        | Exercise time                                                               |
| `CALORIES`                | Active energy burned                                                        |
| `BASAL_ENERGY_BURNED`     | Resting (basal) energy burned                                               |
| `STEPS`                   | Steps                                                                       |
| `FLIGHTS_CLIMBED`         | Flights climbed                                                             |
| `EXERCISE_DISTANCE`       | Distance (walking/running, cycling, swimming, wheelchair)                   |
| `SWIMMING_SUMMARY`        | Swimming stroke count                                                       |
| `LOCATION`                | Workout route                                                               |
| `SPEED`                   | Walking speed (iOS 14+), running speed (16+), cycling speed & cadence (17+) |
| `POWER`                   | Running power (iOS 16+), cycling power (17+)                                |
| `MINDFULNESS`             | Mindful sessions                                                            |

## Heart & cardiovascular

| `CustomPermissions` value | HealthKit type(s) requested           |
| ------------------------- | ------------------------------------- |
| `HEART_RATE`              | Heart rate                            |
| `RESTING_HEART_RATE`      | Resting heart rate                    |
| `HEART_RATE_VARIABILITY`  | Heart rate variability (SDNN)         |
| `INTERBEAT`               | Beat-to-beat measurements             |
| `ELECTROCARDIOGRAM`       | Electrocardiograms (iOS 14+)          |
| `VO2MAX`                  | VO₂ max                               |
| `BLOOD_PRESSURE`          | Blood pressure (systolic & diastolic) |

## Vitals

| `CustomPermissions` value | HealthKit type(s) requested                       |
| ------------------------- | ------------------------------------------------- |
| `RESPIRATORY_RATE`        | Respiratory rate                                  |
| `OXYGEN_SATURATION`       | Blood oxygen                                      |
| `BLOOD_GLUCOSE`           | Blood glucose                                     |
| `BODY_TEMPERATURE`        | Body temperature (+ wrist temperature on iOS 16+) |

## Body measurements

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `HEIGHT`                  | Height                      |
| `WEIGHT`                  | Body mass                   |
| `BMI`                     | Body mass index             |
| `BODY_FAT`                | Body fat percentage         |
| `LEAN_BODY_MASS`          | Lean body mass              |

## Sleep

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `SLEEP_ANALYSIS`          | Sleep analysis              |

## Nutrition

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `NUTRITION_CALORIES`      | Dietary energy consumed     |
| `NUTRITION_PROTEIN`       | Dietary protein             |
| `NUTRITION_CARBOHYDRATES` | Dietary carbohydrates       |
| `NUTRITION_FAT_TOTAL`     | Dietary total fat           |
| `NUTRITION_FIBRE`         | Dietary fiber               |
| `NUTRITION_SUGAR`         | Dietary sugar               |
| `NUTRITION_SODIUM`        | Dietary sodium              |
| `NUTRITION_CHOLESTEROL`   | Dietary cholesterol         |
| `NUTRITION_VITAMIN_C`     | Dietary vitamin C           |
| `NUTRITION_VITAMIN_A`     | Dietary vitamin A           |
| `NUTRITION_WATER`         | Dietary water               |

## Reproductive health

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `MENSTRUATION`            | Menstrual flow              |

## Profile

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `GENDER`                  | Biological sex              |
| `DATE_OF_BIRTH`           | Date of birth               |

## Symptoms

| `CustomPermissions` value | HealthKit type(s) requested |
| ------------------------- | --------------------------- |
| `SYMPTOM_COUGHING`        | Coughing (iOS 13.6+)        |
| `SYMPTOM_FEVER`           | Fever (iOS 13.6+)           |
| `SYMPTOM_SORE_THROAT`     | Sore throat (iOS 13.6+)     |

{% hint style="info" %}
Requesting a data-type group (rather than `customPermissions`) requests a broad superset of types. For example, the **Body** group requests heart rate, HRV, VO₂ max, glucose, blood pressure, body temperature, ECG and more — not just body-composition metrics. Use `customPermissions` when you want the HealthKit prompt to show only specific toggles.
{% endhint %}
{% endtab %}

{% tab title="Health Connect" %}
On Android, the `HEALTH_CONNECT`, `SAMSUNG` and `GOOGLE_FIT` connections all read through **Health Connect** and request the **same** Health Connect permissions. They differ only in which data they return:

* `HEALTH_CONNECT` returns data from **all** apps that write to Health Connect.
* `SAMSUNG` returns only data written by the **Samsung Health** app.
* `GOOGLE_FIT` returns only data written by the **Google Fit** app.

So the permission prompt a user sees is identical across the three; the filtering happens when Terra reads the data.

A dash (—) means the value is **not supported** on Health Connect and requests no data, even if you pass it.

## Activity & workouts

| `CustomPermissions` value | Health Connect record(s) requested                          |
| ------------------------- | ----------------------------------------------------------- |
| `WORKOUT_TYPE`            | Exercise session                                            |
| `ACTIVITY_SUMMARY`        | Exercise session, Active calories, Total calories, Distance |
| `ACTIVE_DURATIONS`        | Exercise session                                            |
| `CALORIES`                | Active calories, Total calories                             |
| `BASAL_ENERGY_BURNED`     | Basal metabolic rate                                        |
| `STEPS`                   | Steps                                                       |
| `FLIGHTS_CLIMBED`         | Floors climbed                                              |
| `EXERCISE_DISTANCE`       | Distance                                                    |
| `SWIMMING_SUMMARY`        | —                                                           |
| `LOCATION`                | —                                                           |
| `SPEED`                   | Speed                                                       |
| `POWER`                   | Power                                                       |
| `MINDFULNESS`             | Exercise session                                            |

## Heart & cardiovascular

| `CustomPermissions` value | Health Connect record(s) requested |
| ------------------------- | ---------------------------------- |
| `HEART_RATE`              | Heart rate                         |
| `RESTING_HEART_RATE`      | Resting heart rate, Heart rate     |
| `HEART_RATE_VARIABILITY`  | Heart rate variability (RMSSD)     |
| `INTERBEAT`               | —                                  |
| `ELECTROCARDIOGRAM`       | —                                  |
| `VO2MAX`                  | VO₂ max                            |
| `BLOOD_PRESSURE`          | Blood pressure                     |

## Vitals

| `CustomPermissions` value | Health Connect record(s) requested |
| ------------------------- | ---------------------------------- |
| `RESPIRATORY_RATE`        | Respiratory rate                   |
| `OXYGEN_SATURATION`       | Oxygen saturation                  |
| `BLOOD_GLUCOSE`           | Blood glucose                      |
| `BODY_TEMPERATURE`        | Body temperature                   |

## Body measurements

| `CustomPermissions` value | Health Connect record(s) requested |
| ------------------------- | ---------------------------------- |
| `HEIGHT`                  | Height                             |
| `WEIGHT`                  | Weight                             |
| `BMI`                     | Weight, Height                     |
| `BODY_FAT`                | Body fat                           |
| `LEAN_BODY_MASS`          | Lean body mass                     |

## Sleep

| `CustomPermissions` value | Health Connect record(s) requested |
| ------------------------- | ---------------------------------- |
| `SLEEP_ANALYSIS`          | Sleep session                      |

## Nutrition

| `CustomPermissions` value                      | Health Connect record(s) requested |
| ---------------------------------------------- | ---------------------------------- |
| `NUTRITION_*` (all macro/micronutrient values) | Nutrition                          |
| `NUTRITION_WATER`                              | Hydration                          |

## Reproductive health

| `CustomPermissions` value | Health Connect record(s) requested                       |
| ------------------------- | -------------------------------------------------------- |
| `MENSTRUATION`            | Menstruation flow (+ Menstruation period on Android 14+) |

## Profile

| `CustomPermissions` value | Health Connect record(s) requested |
| ------------------------- | ---------------------------------- |
| `GENDER`                  | —                                  |
| `DATE_OF_BIRTH`           | —                                  |
| {% endtab %}              |                                    |

{% tab title="Samsung Health (direct)" %}
{% hint style="info" %}
This applies only to the **Samsung-specific SDK builds** that integrate the Samsung Health SDK directly. On the standard SDK, the `SAMSUNG` connection reads Samsung Health data **through Health Connect** — see the Health Connect mapping. If you are not on a Samsung-tagged build, use that table.
{% endhint %}

On Samsung-tagged builds, the `SAMSUNG` connection requests Samsung Health data types directly (read access only). A dash (—) means the value is **not supported** and requests no data.

## Activity & workouts

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `WORKOUT_TYPE`            | Activity summary, Exercise            |
| `ACTIVITY_SUMMARY`        | Activity summary, Exercise            |
| `ACTIVE_DURATIONS`        | Activity summary, Exercise            |
| `CALORIES`                | Activity summary, Exercise            |
| `BASAL_ENERGY_BURNED`     | —                                     |
| `STEPS`                   | Steps                                 |
| `FLIGHTS_CLIMBED`         | Floors climbed                        |
| `EXERCISE_DISTANCE`       | Activity summary, Exercise            |
| `SWIMMING_SUMMARY`        | Activity summary, Exercise            |
| `LOCATION`                | Exercise location                     |
| `SPEED`                   | —                                     |
| `POWER`                   | —                                     |
| `MINDFULNESS`             | Activity summary, Exercise            |

## Heart & cardiovascular

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `HEART_RATE`              | Heart rate                            |
| `RESTING_HEART_RATE`      | Heart rate                            |
| `HEART_RATE_VARIABILITY`  | —                                     |
| `INTERBEAT`               | —                                     |
| `ELECTROCARDIOGRAM`       | —                                     |
| `VO2MAX`                  | —                                     |
| `BLOOD_PRESSURE`          | Blood pressure                        |

## Vitals

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `RESPIRATORY_RATE`        | Sleep                                 |
| `OXYGEN_SATURATION`       | Blood oxygen                          |
| `BLOOD_GLUCOSE`           | Blood glucose                         |
| `BODY_TEMPERATURE`        | Body temperature                      |

## Body measurements

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `HEIGHT`                  | Body composition                      |
| `WEIGHT`                  | Body composition                      |
| `BMI`                     | Body composition                      |
| `BODY_FAT`                | Body composition                      |
| `LEAN_BODY_MASS`          | Body composition                      |

## Sleep

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `SLEEP_ANALYSIS`          | Sleep                                 |

## Nutrition

| `CustomPermissions` value                      | Samsung Health data type(s) requested |
| ---------------------------------------------- | ------------------------------------- |
| `NUTRITION_*` (all macro/micronutrient values) | Nutrition                             |
| `NUTRITION_WATER`                              | Water intake                          |

## Reproductive health

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `MENSTRUATION`            | —                                     |

## Profile

| `CustomPermissions` value | Samsung Health data type(s) requested |
| ------------------------- | ------------------------------------- |
| `GENDER`                  | User profile                          |
| `DATE_OF_BIRTH`           | User profile                          |

{% hint style="info" %}
Several metrics that are **not supported** on the Samsung direct integration (`HEART_RATE_VARIABILITY`, `VO2MAX`, `SPEED`, `POWER`, `BASAL_ENERGY_BURNED`, `MENSTRUATION`) **are** available when reading Samsung data via Health Connect, so the Health Connect path offers wider coverage for those metrics.
{% endhint %}
{% endtab %}
{% endtabs %}

## Types

### SuccessMessage

```dart
class SuccessMessage {
  final bool? success;
  final String? error;
}
```

### DataMessage

```dart
class DataMessage {
  final bool? success;
  final Map<String, dynamic>? data;
  final String? error;
}
```

When `toWebhook` is `true`, the `data` field contains `{ "reference": "..." }` — a reference ID for the webhook payload. When `false`, `data` contains the full normalized health data map.

### UserId

```dart
class UserId {
  final bool? success;
  final String? userId;
}
```

## **Initialization**

### **initTerra**

Creates and authenticates a Terra SDK instance. This **makes a network call** to Terra's servers to validate your developer ID and reconnect existing users.

```dart
static Future<SuccessMessage?> initTerra(
      String devID,
      String referenceID) async
```

* `String devID` ➡ Your developer ID from the [Terra Dashboard](https://dashboard.tryterra.co).
* `String referenceID` ➡ An identifier for your app's user. This value appears as `reference_id` in webhook payloads and API responses, allowing you to map Terra users back to your own user system.

**returns** `Future<SuccessMessage?>`

{% hint style="warning" %}
You must `await` this call and verify `success` is `true` before calling any other SDK function.

**Android note:** On Android, the native `Terra.instance` call always reports `success: true` even if an error occurred — check the `error` field for the actual status.
{% endhint %}

## **Connection setup/management**

### initConnection

Authenticates a new user connection with Terra's servers and triggers the platform permission dialog (HealthKit on iOS, Health Connect on Android). This **makes a network call**.

This function should only be called **once** per user/connection type. On subsequent app launches, `initTerra` will automatically reconnect existing users.

```dart
static Future<SuccessMessage?> initConnection(
      Connection connection,
      String token,
      bool schedulerOn,
      List<CustomPermission> customPermissions) async
```

* `Connection connection` ➡ The connection type (e.g. `Connection.appleHealth`, `Connection.samsung`). Must match the platform.
* `String token` ➡ A **single-use** authentication token from the [Generate Authentication Token](https://docs.tryterra.co/reference/generate-authentication-token) endpoint.
* `bool schedulerOn` ➡ Enables automatic data delivery. On **iOS**, enables HealthKit background delivery (also requires `setUpBackgroundDelivery` in AppDelegate). On **Android**, enables periodic WorkManager-based data fetches.
* `List<CustomPermission> customPermissions` ➡ Request specific permissions. Empty list defaults to all scopes.

**returns** `Future<SuccessMessage?>` — check `error` field for specific failure reasons.

### getUserId

Returns the Terra user ID for a connection, or `null` if no connection exists. This is a local read with no network call.

```dart
static Future<UserId?> getUserId(Connection connection) async
```

* `Connection connection` ➡ The connection to get the user ID for.

**returns** `Future<UserId?>` — `userId` is `null` if no connection exists.

## Data retrieval

All data retrieval functions **make network calls** — even with `toWebhook = false`, the SDK sends data to Terra's normalization servers and returns the normalized result.

{% hint style="info" %}
**`toWebhook` behavior:**

Both paths require network connectivity.
{% endhint %}

| `toWebhook`      | What happens                                      | `DataMessage.data` contains                    |
| ---------------- | ------------------------------------------------- | ---------------------------------------------- |
| `true` (default) | Data is fetched and sent to your webhook          | `{ "reference": "..." }` — a reference ID only |
| `false`          | Data is fetched, normalized, and returned locally | The full normalized health data map            |

### **getActivity**

Retrieves workout and exercise session data.

```dart
static Future<DataMessage?> getActivity(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

### **getDaily**

Retrieves daily summary data (steps, calories, distance, heart rate, etc.).

```dart
static Future<DataMessage?> getDaily(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

### getBody

Retrieves body measurement data (weight, height, BMI, heart rate, blood pressure, etc.).

```dart
static Future<DataMessage?> getBody(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

{% hint style="info" %}
Unlike iOS and React Native, the Flutter SDK does not have a `latestReading` parameter on `getBody`.
{% endhint %}

### getSleep

Retrieves sleep session data (stages, duration, heart rate during sleep, etc.).

```dart
static Future<DataMessage?> getSleep(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

### **getNutrition**

Retrieves nutrition and meal data.

```dart
static Future<DataMessage?> getNutrition(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

### getMenstruation

Retrieves menstrual cycle data. **iOS only** — throws `MissingPluginException` on Android.

```dart
static Future<DataMessage?> getMenstruation(
      Connection connection, DateTime startDate, DateTime endDate,
      {bool toWebhook = true}) async
```

### getAthlete

Retrieves the user's athlete profile (biographical data, no date range needed). **iOS only** — throws `MissingPluginException` on Android.

```dart
static Future<DataMessage?> getAthlete(
      Connection connection, {bool toWebhook = true}) async
```

**Common parameters for all data getters:**

* `Connection connection` ➡ The connection to get data from.
* `DateTime startDate` ➡ Start of the date range. Converted to UTC before sending to native.
* `DateTime endDate` ➡ End of the date range. Converted to UTC before sending to native.
* (Optional) `bool toWebhook` ➡ Whether to send data to your webhook. Defaults to `true`.

## Android-only methods

These functions are **only available on Android**. They will throw `MissingPluginException` on iOS.

### isHealthConnectAvailable

Checks if Health Connect is available on the device. Local check, no network call.

```dart
static Future<bool> isHealthConnectAvailable() async
```

### getGivenPermissions

Returns the Health Connect permissions currently granted to your app. Returns permission name strings like `"READ_HEART_RATE"`, `"READ_STEPS"`, etc.

```dart
static Future<Set<String>> getGivenPermissions() async
```

{% hint style="warning" %}
Requires a Health Connect-based connection to be initialized first. If no connection exists, the underlying callback may never fire, causing the Future to hang.
{% endhint %}

## iOS-only methods

### setIgnoredSources

Filters out health data from specific apps when reading from Apple Health. Use this to prevent double-counting when a user connects a data source both through Terra's API (e.g. WHOOP, Garmin) and has that same app syncing into Apple Health.

```dart
static Future<void> setIgnoredSources(List<String> sources) async
```

* `List<String> sources` ➡ App bundle identifiers to exclude (e.g. `["com.whoop.app", "com.garmin.connect.mobile"]`).

{% hint style="info" %}

* Takes effect on the next data fetch (including background delivery).
* **Not persisted across app launches** — call this on every app start if needed.
* **Android: this function is a no-op.** It is accepted but does nothing.
  {% endhint %}
