terra-connections

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Terra Connections

Terra 连接功能

Connect users to 150+ wearable devices and health data providers.
将用户与150+款可穿戴设备和健康数据服务商对接。

Supported Providers (150+)

支持的服务商(150+)

Wearables & Fitness Trackers

可穿戴设备与健身追踪器

  • Garmin - All models, full historical data
  • Fitbit - All devices, nutrition support
  • Apple Health - iOS SDK required
  • Oura Ring - Sleep, readiness, activity
  • WHOOP - Recovery, strain, sleep
  • Polar - Training, sleep, activity
  • Withings - Watches, scales, blood pressure
  • Samsung Health - Android SDK required
  • Google Fit / Health Connect - Android SDK required
  • Suunto, Coros, Biostrap, Zepp - Full support
  • Garmin - 全型号支持,可获取完整历史数据
  • Fitbit - 全设备支持,包含营养数据
  • Apple Health - 需要iOS SDK
  • Oura Ring - 睡眠、恢复状态、活动数据
  • WHOOP - 恢复情况、身体负荷、睡眠数据
  • Polar - 训练、睡眠、活动数据
  • Withings - 手表、体重秤、血压计
  • Samsung Health - 需要Android SDK
  • Google Fit / Health Connect - 需要Android SDK
  • Suunto, Coros, Biostrap, Zepp - 全面支持

Nutrition Apps

营养类应用

  • MyFitnessPal - Food logging, macros
  • Cronometer - Detailed nutrition
  • MacrosFirst, FatSecret - Meal tracking
  • MyFitnessPal - 饮食记录、宏量营养数据
  • Cronometer - 详细营养数据
  • MacrosFirst, FatSecret - 饮食追踪

Medical Devices

医疗设备

  • Freestyle Libre - CGM glucose data
  • Dexcom - CGM glucose (special process)
  • Omron - Blood pressure monitors
  • Freestyle Libre - 动态血糖监测(CGM)数据
  • Dexcom - 动态血糖监测(CGM)数据(需特殊流程)
  • Omron - 血压计

Connection Methods

连接方式

Method 1: Widget Flow (Recommended)

方法1:Widget流程(推荐)

Pre-built UI, easiest integration:
python
from terra import Terra

client = Terra(
    dev_id="botaniqalmedtech-testing-SjyfjtG33s",
    api_key="_W7Pm-kAaIf1GA_Se21NnzCaFZjg3Izc"
)
预构建UI,集成最简单:
python
from terra import Terra

client = Terra(
    dev_id="botaniqalmedtech-testing-SjyfjtG33s",
    api_key="_W7Pm-kAaIf1GA_Se21NnzCaFZjg3Izc"
)

Generate widget session

Generate widget session

response = client.authentication.generatewidgetsession( reference_id="user_12345", # Your internal user ID auth_success_redirect_url="https://app.botaniqal.com/success", auth_failure_redirect_url="https://app.botaniqal.com/failure", providers=["FITBIT", "GARMIN", "OURA"] # Optional: filter providers )
widget_url = response.url
response = client.authentication.generatewidgetsession( reference_id="user_12345", # Your internal user ID auth_success_redirect_url="https://app.botaniqal.com/success", auth_failure_redirect_url="https://app.botaniqal.com/failure", providers=["FITBIT", "GARMIN", "OURA"] # Optional: filter providers )
widget_url = response.url

Redirect user to widget_url

Redirect user to widget_url


**User Flow**:
1. User visits widget URL
2. Selects provider (Fitbit, Garmin, etc.)
3. Completes OAuth with provider
4. Redirected to success URL
5. Webhook sent to your endpoint with `type: "auth"`

**用户流程**:
1. 用户访问Widget URL
2. 选择服务商(Fitbit、Garmin等)
3. 完成服务商的OAuth认证
4. 重定向至成功URL
5. 向你的端点发送`type: "auth"`的Webhook

Method 2: Custom UI Flow

方法2:自定义UI流程

Build your own provider selection UI:
python
undefined
自行构建服务商选择UI:
python
undefined

Step 1: Get available integrations

Step 1: Get available integrations

integrations = client.integrations.fetch()
integrations = client.integrations.fetch()

Display provider list in your UI

Display provider list in your UI

Step 2: User selects provider, generate auth URL

Step 2: User selects provider, generate auth URL

response = client.authentication.authenticateuser( resource="FITBIT", # Provider selected by user reference_id="user_12345" )
auth_url = response.auth_url
response = client.authentication.authenticateuser( resource="FITBIT", # Provider selected by user reference_id="user_12345" )
auth_url = response.auth_url

Open auth_url in browser (NOT WebView/iFrame!)

Open auth_url in browser (NOT WebView/iFrame!)


**Important**: Always open auth URLs in a real browser, not WebView or iFrame (OAuth security requirement).

**重要提示**:始终在真实浏览器中打开认证URL,不要使用WebView或iFrame(OAuth安全要求)。

Method 3: Mobile SDK (Required for Apple/Samsung/Health Connect)

方法3:移动SDK(Apple/Samsung/Health Connect必需)

These sources have no web API - mobile SDK required:
iOS (Swift) - Apple Health:
swift
import TerraiOS

// 1. Get token from your backend
let token = await fetchTerraToken()

// 2. Initialize Terra
Terra.initTerra(devId: "botaniqalmedtech-testing-SjyfjtG33s", referenceId: "user_12345")

// 3. Connect to Apple Health
Terra.initConnection(
    type: Connections.APPLE_HEALTH,
    token: token,
    schedulerOn: true  // Enable background sync
) { success, error in
    if success {
        print("Connected to Apple Health!")
    }
}
Android (Kotlin) - Samsung Health / Health Connect:
kotlin
import co.tryterra.terra.Terra

// 1. Get token from your backend
val token = fetchTerraToken()

// 2. Initialize Terra (minSDK 28 required)
Terra.initTerra(
    devId = "botaniqalmedtech-testing-SjyfjtG33s",
    referenceId = "user_12345",
    context = this
)

// 3. Connect to Samsung Health or Health Connect
Terra.initConnection(
    connection = Connections.SAMSUNG,  // or Connections.HEALTH_CONNECT
    token = token,
    context = this,
    schedulerOn = true
) { success ->
    if (success) {
        println("Connected to Samsung Health!")
    }
}
React Native:
javascript
import { Terra, Connections } from "terra-react";

// Initialize
Terra.initTerra("botaniqalmedtech-testing-SjyfjtG33s", "user_12345");

// Connect (iOS: Apple Health, Android: Samsung/Health Connect)
await Terra.initConnection(
    Connections.APPLE_HEALTH,
    authToken,
    true  // schedulerOn for background sync
);
这些数据源没有Web API - 必须使用移动SDK:
iOS (Swift) - Apple Health:
swift
import TerraiOS

// 1. Get token from your backend
let token = await fetchTerraToken()

// 2. Initialize Terra
Terra.initTerra(devId: "botaniqalmedtech-testing-SjyfjtG33s", referenceId: "user_12345")

// 3. Connect to Apple Health
Terra.initConnection(
    type: Connections.APPLE_HEALTH,
    token: token,
    schedulerOn: true  // Enable background sync
) { success, error in
    if success {
        print("Connected to Apple Health!")
    }
}
Android (Kotlin) - Samsung Health / Health Connect:
kotlin
import co.tryterra.terra.Terra

// 1. Get token from your backend
val token = fetchTerraToken()

// 2. Initialize Terra (minSDK 28 required)
Terra.initTerra(
    devId = "botaniqalmedtech-testing-SjyfjtG33s",
    referenceId = "user_12345",
    context = this
)

// 3. Connect to Samsung Health or Health Connect
Terra.initConnection(
    connection = Connections.SAMSUNG,  // or Connections.HEALTH_CONNECT
    token = token,
    context = this,
    schedulerOn = true
) { success ->
    if (success) {
        println("Connected to Samsung Health!")
    }
}
React Native:
javascript
import { Terra, Connections } from "terra-react";

// Initialize
Terra.initTerra("botaniqalmedtech-testing-SjyfjtG33s", "user_12345");

// Connect (iOS: Apple Health, Android: Samsung/Health Connect)
await Terra.initConnection(
    Connections.APPLE_HEALTH,
    authToken,
    true  // schedulerOn for background sync
);

Operations

操作方法

connect-user

connect-user

Connect a user to a wearable provider.
python
def connect_user(
    client: Terra,
    reference_id: str,
    provider: str = None,
    success_url: str = None,
    failure_url: str = None
) -> dict:
    """
    Connect user to wearable provider.

    Args:
        reference_id: Your internal user ID
        provider: Specific provider or None for widget with all
        success_url: Redirect URL on success
        failure_url: Redirect URL on failure

    Returns:
        dict with url and session_id
    """
    if provider:
        # Custom UI flow - specific provider
        response = client.authentication.authenticateuser(
            resource=provider,
            reference_id=reference_id
        )
        return {"url": response.auth_url, "type": "direct"}
    else:
        # Widget flow - user selects provider
        response = client.authentication.generatewidgetsession(
            reference_id=reference_id,
            auth_success_redirect_url=success_url,
            auth_failure_redirect_url=failure_url
        )
        return {
            "url": response.url,
            "session_id": response.session_id,
            "type": "widget"
        }
将用户与可穿戴服务商对接。
python
def connect_user(
    client: Terra,
    reference_id: str,
    provider: str = None,
    success_url: str = None,
    failure_url: str = None
) -> dict:
    """
    Connect user to wearable provider.

    Args:
        reference_id: Your internal user ID
        provider: Specific provider or None for widget with all
        success_url: Redirect URL on success
        failure_url: Redirect URL on failure

    Returns:
        dict with url and session_id
    """
    if provider:
        # Custom UI flow - specific provider
        response = client.authentication.authenticateuser(
            resource=provider,
            reference_id=reference_id
        )
        return {"url": response.auth_url, "type": "direct"}
    else:
        # Widget flow - user selects provider
        response = client.authentication.generatewidgetsession(
            reference_id=reference_id,
            auth_success_redirect_url=success_url,
            auth_failure_redirect_url=failure_url
        )
        return {
            "url": response.url,
            "session_id": response.session_id,
            "type": "widget"
        }

disconnect-user

disconnect-user

Disconnect user and remove their data.
python
def disconnect_user(client: Terra, terra_user_id: str) -> bool:
    """
    Disconnect user from Terra (revokes access, removes data).

    Args:
        terra_user_id: Terra's user ID (not your reference_id)

    Returns:
        bool: Success status
    """
    response = client.authentication.deauthenticateuser(user_id=terra_user_id)
    return response.success
断开用户连接并移除其数据。
python
def disconnect_user(client: Terra, terra_user_id: str) -> bool:
    """
    Disconnect user from Terra (revokes access, removes data).

    Args:
        terra_user_id: Terra's user ID (not your reference_id)

    Returns:
        bool: Success status
    """
    response = client.authentication.deauthenticateuser(user_id=terra_user_id)
    return response.success

get-user-info

get-user-info

Get user's connection status and details.
python
def get_user_info(client: Terra, terra_user_id: str) -> dict:
    """Get information about a connected user."""

    response = client.user.getuser(user_id=terra_user_id)

    return {
        "user_id": response.user.user_id,
        "provider": response.user.provider,
        "reference_id": response.user.reference_id,
        "scopes": response.user.scopes,
        "last_webhook_update": response.user.last_webhook_update
    }
获取用户的连接状态及详情。
python
def get_user_info(client: Terra, terra_user_id: str) -> dict:
    """Get information about a connected user."""

    response = client.user.getuser(user_id=terra_user_id)

    return {
        "user_id": response.user.user_id,
        "provider": response.user.provider,
        "reference_id": response.user.reference_id,
        "scopes": response.user.scopes,
        "last_webhook_update": response.user.last_webhook_update
    }

list-connected-users

list-connected-users

Get all users connected to your app.
python
def list_connected_users(client: Terra) -> list:
    """List all connected Terra users."""

    response = client.user.getsubscriptions()

    users = []
    for user in response.users:
        users.append({
            "user_id": user.user_id,
            "provider": user.provider,
            "reference_id": user.reference_id,
            "last_update": user.last_webhook_update
        })

    return users
获取所有连接到你的应用的用户。
python
def list_connected_users(client: Terra) -> list:
    """List all connected Terra users."""

    response = client.user.getsubscriptions()

    users = []
    for user in response.users:
        users.append({
            "user_id": user.user_id,
            "provider": user.provider,
            "reference_id": user.reference_id,
            "last_update": user.last_webhook_update
        })

    return users

get-users-by-reference

get-users-by-reference

Find Terra users by your internal reference ID.
python
def get_users_by_reference(client: Terra, reference_id: str) -> list:
    """
    Get all Terra users for a reference_id.
    (One person can have multiple providers connected)
    """

    response = client.user.getuser(reference_id=reference_id)

    return response.users  # List of TerraUser objects
通过你的内部参考ID查找Terra用户。
python
def get_users_by_reference(client: Terra, reference_id: str) -> list:
    """
    Get all Terra users for a reference_id.
    (One person can have multiple providers connected)
    """

    response = client.user.getuser(reference_id=reference_id)

    return response.users  # List of TerraUser objects

Multi-Device Setup

多设备配置

One user can connect multiple wearables:
python
undefined
一个用户可连接多款可穿戴设备:
python
undefined

User connects Fitbit

User connects Fitbit

connect_user(client, "user_123", provider="FITBIT")
connect_user(client, "user_123", provider="FITBIT")

Same user connects Oura Ring

Same user connects Oura Ring

connect_user(client, "user_123", provider="OURA")
connect_user(client, "user_123", provider="OURA")

Get all connections for user

Get all connections for user

users = get_users_by_reference(client, "user_123")
users = get_users_by_reference(client, "user_123")

Returns: [TerraUser(provider="FITBIT"), TerraUser(provider="OURA")]

Returns: [TerraUser(provider="FITBIT"), TerraUser(provider="OURA")]


**Each provider creates a separate Terra User ID**, but all share the same `reference_id`.

**每个服务商都会生成独立的Terra用户ID**,但所有用户ID共享同一个`reference_id`。

Provider-Specific Notes

服务商专属说明

Apple Health (iOS)

Apple Health (iOS)

  • Requires: Mobile SDK, iOS 13+
  • No web API: Must use native app
  • Background sync: Enable
    schedulerOn: true
  • Permissions: Request during connection
  • 要求:移动SDK,iOS 13+
  • 无Web API:必须使用原生应用
  • 后台同步:启用
    schedulerOn: true
  • 权限:在连接过程中请求

Samsung Health / Health Connect (Android)

Samsung Health / Health Connect (Android)

  • Requires: Mobile SDK, minSDK 28
  • Health Connect: Google's unified health API
  • Samsung specific: Uses Samsung Health SDK
  • 要求:移动SDK,最低SDK版本28
  • Health Connect:谷歌统一健康API
  • 三星专属:使用Samsung Health SDK

WHOOP

WHOOP

  • Special process: Contact Terra for activation
  • Data: Recovery, strain, sleep, HRV
  • 特殊流程:联系Terra激活
  • 数据:恢复情况、身体负荷、睡眠、心率变异性(HRV)

Dexcom (CGM)

Dexcom (CGM)

  • Special process: Contact Terra for activation
  • Data: Continuous glucose monitoring
  • 特殊流程:联系Terra激活
  • 数据:连续血糖监测

Freestyle Libre (EU)

Freestyle Libre (欧盟)

  • Dedicated API keys: Required for EU
  • Data: CGM glucose readings
  • 专属API密钥:欧盟地区必需
  • 数据:动态血糖监测读数

Strava

Strava

  • Dedicated API keys: Required
  • Data: Activities, routes
  • 专属API密钥:必需
  • 数据:活动记录、路线

Webhook Events for Connections

连接相关Webhook事件

When user connects/disconnects, you receive webhooks:
Connection Success (
type: "auth"
):
json
{
  "type": "auth",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT",
    "reference_id": "user_12345"
  },
  "status": "authenticated"
}
Disconnection (
type: "deauth"
):
json
{
  "type": "deauth",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT"
  },
  "status": "deauthenticated"
}
Connection Error (
type: "connection_error"
):
json
{
  "type": "connection_error",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT"
  },
  "message": "Token refresh failed"
}
当用户连接/断开时,你会收到Webhook:
连接成功 (
type: "auth"
):
json
{
  "type": "auth",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT",
    "reference_id": "user_12345"
  },
  "status": "authenticated"
}
断开连接 (
type: "deauth"
):
json
{
  "type": "deauth",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT"
  },
  "status": "deauthenticated"
}
连接错误 (
type: "connection_error"
):
json
{
  "type": "connection_error",
  "user": {
    "user_id": "terra_abc123",
    "provider": "FITBIT"
  },
  "message": "Token refresh failed"
}

Database Schema Recommendation

数据库Schema推荐

sql
CREATE TABLE terra_connections (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),  -- Your user
    terra_user_id VARCHAR(255) UNIQUE,     -- Terra's user ID
    provider VARCHAR(50),                   -- FITBIT, GARMIN, etc.
    reference_id VARCHAR(255),              -- Your reference ID
    connected_at TIMESTAMP DEFAULT NOW(),
    last_sync TIMESTAMP,
    status VARCHAR(20) DEFAULT 'active',    -- active, disconnected
    scopes TEXT[]                           -- Granted permissions
);

CREATE INDEX idx_terra_user ON terra_connections(user_id);
CREATE INDEX idx_terra_reference ON terra_connections(reference_id);
sql
CREATE TABLE terra_connections (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),  -- Your user
    terra_user_id VARCHAR(255) UNIQUE,     -- Terra's user ID
    provider VARCHAR(50),                   -- FITBIT, GARMIN, etc.
    reference_id VARCHAR(255),              -- Your reference ID
    connected_at TIMESTAMP DEFAULT NOW(),
    last_sync TIMESTAMP,
    status VARCHAR(20) DEFAULT 'active',    -- active, disconnected
    scopes TEXT[]                           -- Granted permissions
);

CREATE INDEX idx_terra_user ON terra_connections(user_id);
CREATE INDEX idx_terra_reference ON terra_connections(reference_id);

Related Skills

相关技能

  • terra-auth: Authentication and credentials
  • terra-data: Retrieve health data
  • terra-webhooks: Handle connection events
  • terra-sdk: Mobile SDK integration
  • terra-auth: 认证与凭证管理
  • terra-data: 健康数据获取
  • terra-webhooks: 连接事件处理
  • terra-sdk: 移动SDK集成