# Flutter

## Connections

| Value                      | Platform | Description                                                  |
| -------------------------- | -------- | ------------------------------------------------------------ |
| `Connection.appleHealth`   | iOS      | Apple Health (HealthKit)                                     |
| `Connection.samsung`       | Android  | Samsung Health (direct SDK access)                           |
| `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. 41 values available — see `lib/models/enums.dart` for the full list.

Notable platform gaps: `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**.

## 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:**
{% 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            |

{% hint style="info" %}
Both paths require network connectivity.
{% endhint %}

### **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 %}
