terra-troubleshooting

Terra API troubleshooting and debugging. Use when experiencing connection issues, data sync problems, webhook failures, SDK errors, or provider-specific issues.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "terra-troubleshooting" with this command: npx skills add adaptationio/skrillz/adaptationio-skrillz-terra-troubleshooting

Terra Troubleshooting

Diagnose and resolve common Terra API issues.

Quick Diagnostics

from terra import Terra

def check_terra_health(client: Terra) -> dict:
    """Run basic health checks."""
    results = {}

    # 1. API connectivity
    try:
        integrations = client.integrations.fetch()
        results["api_connection"] = f"OK - {len(integrations.integrations)} providers"
    except Exception as e:
        results["api_connection"] = f"FAILED - {e}"

    # 2. List connected users
    try:
        users = client.user.getsubscriptions()
        results["connected_users"] = f"OK - {len(users.users)} users"
    except Exception as e:
        results["connected_users"] = f"FAILED - {e}"

    return results

# Usage
client = Terra(dev_id="...", api_key="...")
print(check_terra_health(client))

Common Issues

Authentication Issues

"Invalid API key or dev-id"

Cause: Incorrect credentials or wrong environment.

Solution:

# Check you're using correct environment credentials
ENVIRONMENTS = {
    "testing": {
        "dev_id": "botaniqalmedtech-testing-SjyfjtG33s",
        "api_key": "_W7Pm-kAaIf1GA_Se21NnzCaFZjg3Izc"
    },
    "staging": {
        "dev_id": "botaniqalmedtech-staging-uGKHOPRCi1",
        "api_key": "fJia30spa-EqB_CMqZBzzrkMWZ_u2pv_"
    },
    "production": {
        "dev_id": "botaniqalmedtech-prod-yrc99AwsT2",
        "api_key": "Il4YUTc-e00EcvKGUx63j7YE3MJ-7QIz"
    }
}

# Verify connection
from terra import Terra
client = Terra(**ENVIRONMENTS["testing"])
print(client.integrations.fetch())

Widget session expired

Cause: Session URLs expire after 15 minutes.

Solution: Generate a new widget session:

response = client.authentication.generatewidgetsession(
    reference_id="user_123",
    auth_success_redirect_url="https://app.example.com/success",
    auth_failure_redirect_url="https://app.example.com/failure"
)
# Redirect user to response.url immediately

Mobile SDK token invalid

Cause: Token expired (3 min) or already used.

Solution: Generate fresh token for each connection attempt:

# Backend generates new token each time
token = client.authentication.generateauthtoken(reference_id="user_123")
# Send token.token to mobile app
# Token is one-time use - generate new one if connection fails

Connection Issues

User stuck on "connecting"

Cause: OAuth flow interrupted or WebView used.

Solution:

  1. Never use WebView/iFrame for OAuth
  2. Open auth URL in real browser
  3. Handle redirects properly:
// Wrong - WebView blocks OAuth
<WebView source={{ uri: authUrl }} />

// Correct - Open in browser
import { Linking } from 'react-native';
Linking.openURL(authUrl);

// Or use InAppBrowser
import { InAppBrowser } from 'react-native-inappbrowser-reborn';
InAppBrowser.open(authUrl);

Provider returns "Access Denied"

Cause: Provider-side issue or insufficient permissions.

Solution:

# Check user's granted scopes
user = client.user.getuser(user_id="terra_abc123")
print(f"Scopes: {user.user.scopes}")

# If missing scopes, user needs to reconnect and grant all permissions

WHOOP / Dexcom connection fails

Cause: These require special activation.

Solution: Contact Terra support at [email protected] for:

  • WHOOP access activation
  • Dexcom (CGM) access activation
  • Freestyle Libre EU dedicated API keys
  • Strava dedicated API keys

Data Sync Issues

No data received

Causes:

  1. User just connected (data takes time to sync)
  2. User has no data in that date range
  3. Provider is "polled" type (5-min delay)

Solution:

from datetime import datetime, timedelta

def check_user_data(client: Terra, user_id: str) -> dict:
    """Check if user has any data."""
    end = datetime.now()
    start = end - timedelta(days=7)

    results = {}

    # Check each data type
    for data_type in ["daily", "activity", "sleep", "body"]:
        try:
            method = getattr(client, data_type)
            response = method.get(user_id=user_id, start_date=start, end_date=end)
            results[data_type] = len(response.data)
        except Exception as e:
            results[data_type] = f"Error: {e}"

    return results

print(check_user_data(client, "terra_abc123"))

Duplicate data received

Cause: Daily/body data updates multiple times per day.

Solution: Use UPSERT pattern, not INSERT:

# Wrong - creates duplicates
db.insert(data)

# Correct - overwrites existing
db.upsert(
    {"user_id": user_id, "date": date},
    {"$set": data}
)

Historical data missing

Cause: Provider limits historical access.

Reference - Maximum historical data per provider:

ProviderLimit
Garmin5 years
Fitbit10 years
Oura3 years
WHOOP2 years
Polar30 days
COROS3 months

Webhook Issues

Webhooks not received

Checklist:

  1. Check webhook configured in dashboard:

    • Terra Dashboard → Destinations → Webhooks
    • Verify URL is correct and HTTPS
  2. Check endpoint is accessible:

    curl -X POST https://your-webhook-url.com/terra \
      -H "Content-Type: application/json" \
      -d '{"type": "test"}'
    
  3. Check server logs for incoming requests

  4. Verify IP not blocked - Terra IPs:

    18.133.218.210, 18.169.82.189, 18.132.162.19,
    18.130.218.186, 13.43.183.154, 3.11.208.36,
    35.214.201.105, 35.214.230.71, 35.214.252.53, 35.214.229.114
    

Signature verification failing

Causes:

  1. Wrong signing secret
  2. Body modified before verification
  3. Incorrect signature algorithm

Solution:

import hmac
import hashlib

def debug_signature(header: str, body: bytes, secret: str):
    """Debug signature verification."""

    # Parse header
    parts = dict(p.split("=") for p in header.split(","))
    print(f"Timestamp: {parts['t']}")
    print(f"Received signature: {parts['v1']}")

    # Compute expected
    message = f"{parts['t']}.{body.decode()}"
    expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
    print(f"Expected signature: {expected}")

    # Compare
    match = hmac.compare_digest(expected, parts['v1'])
    print(f"Match: {match}")

    return match

# Use in webhook handler
@app.route("/webhook", methods=["POST"])
def webhook():
    header = request.headers.get("terra-signature")
    body = request.get_data()  # Must be raw bytes, not parsed JSON!

    if not debug_signature(header, body, SIGNING_SECRET):
        return "Invalid signature", 401

    # Now parse JSON
    payload = request.get_json()

Critical: Get raw body BEFORE parsing JSON.

Webhook timeouts

Cause: Processing takes too long (>5 seconds recommended).

Solution: Process asynchronously:

from celery import Celery

celery = Celery()

@app.route("/webhook", methods=["POST"])
def webhook():
    # Verify signature
    # Queue for async processing
    process_webhook.delay(request.get_json())

    # Respond immediately
    return "OK", 200

@celery.task
def process_webhook(payload):
    # Do heavy processing here
    save_to_database(payload)
    send_notifications(payload)

SDK Issues

iOS: Apple Health no data

Causes:

  1. Permissions not granted
  2. Background delivery not enabled
  3. App not authorized in Health app

Solution:

// 1. Check permissions in code
Terra.checkPermissions { granted in
    if !granted {
        // Request permissions again
        Terra.requestPermissions()
    }
}

// 2. Enable background delivery
func application(_ app: UIApplication, didFinishLaunchingWithOptions...) {
    Terra.setUpBackgroundDelivery()
}

// 3. User must enable in Settings → Privacy → Health → Your App

Android: Samsung Health fails

Causes:

  1. Samsung Health app not installed
  2. minSDK < 28
  3. Missing permissions

Solution:

// 1. Check Samsung Health installed
if (!Terra.isSamsungHealthAvailable(context)) {
    // Prompt user to install Samsung Health
    showInstallSamsungHealthDialog()
}

// 2. Verify minSDK in build.gradle
android {
    defaultConfig {
        minSdkVersion 28  // Required for Terra Android SDK
    }
}

// 3. Request permissions
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.BODY_SENSORS"/>

Android: Health Connect issues

Cause: Health Connect not installed or configured.

Solution:

// Check Health Connect availability
if (!Terra.isHealthConnectAvailable(context)) {
    // Prompt to install Health Connect
    val intent = Intent(Intent.ACTION_VIEW).apply {
        data = Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata")
    }
    startActivity(intent)
}

React Native: Build failures

Common fixes:

# iOS: Clean and rebuild
cd ios
pod deintegrate
pod install
cd ..
npx react-native run-ios

# Android: Clean build
cd android
./gradlew clean
cd ..
npx react-native run-android

Provider-Specific Issues

MyFitnessPal: Gateway timeout

Cause: MyFitnessPal API is slow/unreliable.

Solution: Retry with exponential backoff:

import time

def fetch_with_retry(client, user_id, start, end, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.nutrition.get(user_id, start, end)
        except Exception as e:
            if "timeout" in str(e).lower() and attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # 1, 2, 4 seconds
                continue
            raise

Garmin: Data delayed

Cause: Garmin is a "polled" provider (~5 min sync).

Solution: Wait for webhook rather than polling API:

# Don't poll repeatedly
# Instead, wait for webhook notification

Fitbit: Token revoked

Cause: User revoked access in Fitbit app.

Solution: Handle access_revoked webhook:

def handle_access_revoked(payload):
    user_id = payload["user"]["user_id"]

    # Mark user as disconnected
    db.terra_users.update_one(
        {"terra_user_id": user_id},
        {"$set": {"status": "access_revoked"}}
    )

    # Notify user to reconnect
    send_reconnect_notification(user_id)

Debug Mode

Enable detailed logging:

import logging

# Enable Terra SDK logging
logging.getLogger("terra").setLevel(logging.DEBUG)

# Or enable all HTTP logging
import http.client
http.client.HTTPConnection.debuglevel = 1

Support Escalation

If issues persist:

  1. Check Terra Status: https://status.tryterra.co
  2. Documentation: https://docs.tryterra.co
  3. Email Support: [email protected]
  4. Include in support request:
    • Dev ID (not API key!)
    • User ID (if applicable)
    • Error message
    • Timestamp of issue
    • Provider affected

Health Check Script

#!/usr/bin/env python3
"""Terra API health check script."""

from terra import Terra
from datetime import datetime, timedelta

def run_health_check():
    print("=" * 50)
    print("Terra API Health Check")
    print("=" * 50)

    # Test each environment
    envs = {
        "testing": ("botaniqalmedtech-testing-SjyfjtG33s", "_W7Pm-kAaIf1GA_Se21NnzCaFZjg3Izc"),
        "staging": ("botaniqalmedtech-staging-uGKHOPRCi1", "fJia30spa-EqB_CMqZBzzrkMWZ_u2pv_"),
        "production": ("botaniqalmedtech-prod-yrc99AwsT2", "Il4YUTc-e00EcvKGUx63j7YE3MJ-7QIz"),
    }

    for env_name, (dev_id, api_key) in envs.items():
        print(f"\n{env_name.upper()}:")
        try:
            client = Terra(dev_id=dev_id, api_key=api_key)

            # Check API
            integrations = client.integrations.fetch()
            print(f"  ✅ API Connected - {len(integrations.integrations)} providers")

            # Check users
            users = client.user.getsubscriptions()
            print(f"  ✅ Users: {len(users.users)} connected")

        except Exception as e:
            print(f"  ❌ Error: {e}")

    print("\n" + "=" * 50)
    print("Health check complete")

if __name__ == "__main__":
    run_health_check()

Related Skills

  • terra-auth: Credential management
  • terra-connections: Connection flows
  • terra-webhooks: Webhook handling
  • terra-data: Data retrieval
  • terra-sdk: SDK integration

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

finnhub-api

No summary provided by upstream source.

Repository SourceNeeds Review
General

auto-updater

No summary provided by upstream source.

Repository SourceNeeds Review
General

todo-management

No summary provided by upstream source.

Repository SourceNeeds Review
General

alphavantage-api

No summary provided by upstream source.

Repository SourceNeeds Review