apple-wholeiOS (Swift)

Connections

The iOS SDK supports the following connection types:

Value
Description

Connections.APPLE_HEALTH

Apple Health (HealthKit)

Connections.FREESTYLE_LIBRE

FreeStyle Libre (NFC sensor)

CustomPermissions

Use these to request a subset of permissions instead of all available ones. When not specified, all permissions from your developer scopes are requested.

WORKOUT_TYPES, ACTIVITY_SUMMARY, LOCATION, CALORIES, STEPS, HEART_RATE, HEART_RATE_VARIABILITY, VO2MAX, HEIGHT, ACTIVE_DURATIONS, WEIGHT, FLIGHTS_CLIMBED, BMI, BODY_FAT, EXERCISE_DISTANCE, GENDER, DATE_OF_BIRTH, BASAL_ENERGY_BURNED, SWIMMING_SUMMARY, RESTING_HEART_RATE, BLOOD_PRESSURE, BLOOD_GLUCOSE, BODY_TEMPERATURE, MINDFULNESS, LEAN_BODY_MASS, OXYGEN_SATURATION, SLEEP_ANALYSIS, RESPIRATORY_RATE, NUTRITION_SODIUM, NUTRITION_PROTEIN, NUTRITION_CARBOHYDRATES, NUTRITION_FIBRE, NUTRITION_FAT_TOTAL, NUTRITION_SUGAR, NUTRITION_VITAMIN_C, NUTRITION_VITAMIN_A, NUTRITION_CALORIES, NUTRITION_WATER, NUTRITION_CHOLESTEROL, MENSTRUATION, INTERBEAT, SPEED, POWER, ELECTROCARDIOGRAM

Initialization

Terra.instance

Creates and authenticates a TerraManager instance. This makes a network call to Terra's servers to validate your developer ID and retrieve your account configuration.

If an existing Apple Health user is found for this device, the SDK will automatically reconnect — this may trigger the HealthKit permission popup and start background delivery if previously configured.

Terra.instance(devId: String,
               referenceId: String?,
               completion: @escaping (TerraManager?, TerraError?) -> Void)
  • devId: String ➡ Your developer ID from the Terra Dashboardarrow-up-right.

  • referenceId: String? ➡ 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.

  • completion: @escaping (TerraManager?, TerraError?) -> Void ➡ Called when initialization completes. You must wait for this callback before calling any other SDK function. On failure, TerraManager will be nil and TerraError will describe the issue.

circle-exclamation

Possible errors:

Error
Cause

TerraError.InvalidDevID

The devId is not recognized by Terra

TerraError.NoInternet

Network request failed

TerraError.HealthKitUnavailable

Device does not support HealthKit (e.g. iPad)

Static methods on Terra

setUpBackgroundDelivery

Registers HealthKit observer queries and a BGTaskScheduler task to automatically send new health data to your webhook destination, even when your app is in the background.

This is a static method on the Terra class (not on TerraManager). It must be called in your AppDelegate's didFinishLaunchingWithOptions.

Delivery frequency by data type:

Data type
Frequency

Activity, Sleep, Daily

Immediate (on new data)

Body, Nutrition, Menstruation

Hourly

circle-info

Prerequisites:

  • Terra.instance must have been called at least once previously (the SDK uses your stored scopes to determine which data types to observe).

  • Your app's Info.plist must include co.tryterra.data.post.request in the BGTaskSchedulerPermittedIdentifiers array.

  • HealthKit Background Delivery and Background Processing capabilities must be enabled in Xcode.

If a data post fails due to no network, the SDK caches the payload and retries via BGTaskScheduler when connectivity is restored.

checkAuthentication

Checks whether a connection is authenticated by making a network call to Terra's servers.

  • connection: Connections ➡ The connection type to check.

  • devId: String ➡ Your developer ID.

  • completion: @escaping (Bool) -> Voidtrue if the connection is authenticated on the server, false otherwise (including network failures).

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.

  • ignored: [String] ➡ An array of app bundle identifiers to exclude (e.g. ["com.whoop.app", "com.garmin.connect.mobile"]). Any HealthKit samples originating from these apps will be filtered out of all data reads.

circle-info
  • Can be called at any time — takes effect on the next data fetch (including background delivery).

  • Not persisted across app launches — call this on every app start if needed.

  • Does not affect which data sources can write to HealthKit, only what the Terra SDK reads.

TerraManager Instance methods

All methods below are called on the TerraManager instance returned by Terra.instance.

Connection setup/management

initConnection

Authenticates a new user connection with Terra's servers and triggers the platform permission dialog. This makes a network call and, for Apple Health, shows the HealthKit permission popup.

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

  • type: Connections ➡ The connection type to initialize (e.g. .APPLE_HEALTH).

  • token: String ➡ A single-use authentication token generated from your backend server via the Generate Authentication Tokenarrow-up-right endpoint. Each token can only be used once.

  • (Optional) customReadTypes: Set<CustomPermissions> ➡ Customize which permissions appear in the HealthKit popup. When empty, defaults to all permissions from your developer scopes.

  • schedulerOn: Bool ➡ Enables background delivery of health data. Defaults to true. When enabled, new data is automatically sent to your webhook destination. Requires calling Terra.setUpBackgroundDelivery() in your AppDelegate for background delivery to function.

  • completion: @escaping (Bool, TerraError?) -> Void ➡ Called when the connection is established (or fails).

Possible errors:

Error
Cause

TerraError.InvalidDevID

Developer ID not recognized

TerraError.InvalidToken

Token is invalid or already used

TerraError.UserLimitsReached

Your plan's user limit has been reached

TerraError.NoInternet

Network request failed

TerraError.HealthKitUnavailable

Device does not support HealthKit

getUserId

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

The returned user_id is the same identifier used in webhook payloads, API requests, and the Terra dashboard.

  • type: Connections ➡ The connection to retrieve the user ID for.

Returns nil when:

  • initConnection was never called for this connection type

  • No existing user was found during Terra.instance initialization

  • The connection failed

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.

Each function accepts dates as either Date or TimeInterval (Unix timestamp). Each also accepts an optional withSamples: Bool? = nil parameter.

circle-info

toWebhook behavior:

toWebhook

What happens

Completion returns

true (default)

Data is fetched from the health source and sent to your webhook destination

A reference ID string only (not the data itself)

false

Data is fetched, sent to Terra for normalization, and the normalized payload is returned locally

The full normalized data payload

circle-info

Both paths require network connectivity.

circle-info

withSamples parameter: Controls whether the server includes granular time-series sample arrays in the response. When nil (default), the server uses its default behavior. Set to true to explicitly request samples, or false to exclude them for smaller payloads.

Date ranges over 31 days are automatically chunked into weekly segments and processed serially.

getActivity

Retrieves workout and activity data (exercise sessions, mindfulness sessions, heart rate during workouts, GPS routes, etc.).

getDaily

Retrieves daily summary data (total steps, calories, distance, resting heart rate, HRV, floors climbed, etc.).

getSleep

Retrieves sleep session data (sleep stages, duration, heart rate during sleep, HRV, SpO2, respiratory rate).

getBody

Retrieves body measurement data (weight, height, BMI, body fat, heart rate, HRV, blood pressure, blood glucose, SpO2, body temperature, ECG).

  • latestReading: Bool ➡ When true, ignores the date range and returns only the single most recent reading for each body metric (weight, height, BMI, etc.). Heart rate and HRV samples still use the date range. Only available on the Date overload (not TimeInterval). Defaults to false.

getNutrition

Retrieves nutrition and meal data (macronutrients, micronutrients, water intake, individual meals).

getMenstruation

Retrieves menstrual cycle data.

getAthlete

Retrieves the user's athlete profile (biographical data, no date range needed).

Completion parameters (same structure for all data getters):

  • Booltrue if the request succeeded.

  • Payload? ➡ When toWebhook: true, contains only a reference string. When toWebhook: false, contains the full normalized data. nil on failure.

  • TerraError? ➡ Describes the error if the request failed. Possible values: TerraError.Unauthenticated (no connection for this type), TerraError.UnsupportedResource (e.g. calling getActivity with FREESTYLE_LIBRE).

subscribe

Registers for real-time data updates via HealthKit anchored object queries. When new data arrives, the Terra.updateHandler closure is called with the new samples.

  • forDataTypes: Set<DataTypes> ➡ Data types to subscribe to. Available values: STEPS, HEART_RATE, HEART_RATE_VARIABILITY, CALORIES, DISTANCE.

Before calling subscribe, you must set the update handler:

Set this in your AppDelegate's didFinishLaunchingWithOptions so it persists across app launches. The handler is called both for real-time updates and for catching up on data that arrived while the app was closed.

Writing data

These functions write data directly into Apple Health. No network calls are made — data is written to the local HealthKit store.

postActivity

Writes a workout to Apple Health.

  • type: The connection type (e.g. .APPLE_HEALTH).

  • payload: A TerraActivityData object. Required fields: metadata.start_time, metadata.end_time, and at least one field in device_data. Optional: distance_data.summary.distance_meters, calories_data.net_activity_calories.

  • completion: Bool for success, TerraError? for errors (e.g. StartTimeCannotBeNil, InvalidDateFormat, InvalidDevice, PermissionsDenied).

postNutrition

Writes nutrition data (a food entry with macros/micros) to Apple Health.

  • payload: A TerraNutritionData object with metadata.start_time/end_time and nutrition values in summary.macros/summary.micros. Supports 33+ nutrient types.

  • completion: Bool only (no TerraError). Returns false if dates are invalid, all write permissions are denied, or the HealthKit save fails.

postBody

Writes body measurement data to Apple Health (weight, height, BMI, heart rate, blood pressure, glucose, SpO2, temperature, etc.).

  • payload: A TerraBodyData object with measurement samples.

  • completion: Bool only (no TerraError). Returns false if dates are invalid or HealthKit save fails.

Last updated

Was this helpful?