Requesting historical health data (REST API requests)

Learn how to request for historical data to be sent to your destination through the REST API

Overview

Terra API is event-based, meaning you don’t need to manually request data via the API.

For new and ongoing data updates, Terra API automatically sends them to your configured Data Destination (e.g. Webhook, Database, or cloud storage bucket).

If you need historical user data, you can request it using the Health & Fitness API endpoints by specifying the user ID, data type, and time range. This allows you to request past records on demand.

In this guide you will learn:

  1. When are historical data requests useful?

  2. How to use the Terra Dashboard to make a historical data request?

  3. How to use the Terra's Health & Fitness API to make a historical data request?

  4. Request Parameters (e.g. send to destination and include samples)

  5. How to handle requests of very long time ranges ?

Prerequisites


1. When to request historical data?

a. Upon creating a New User

When an end user first connects an account (e.g. wearable, device, health app), you will by default only receive data from that point onwards.

If you would like to build a historical health & fitness profile of the user, to establish baselines for statistics, or for any other calculations, you can make a request to Terra for data from prior to the user's authentication.

Time Range limits in Historical Data Requests

Some providers impose limits on how far back a developer can request data. Those are:

  • Garmin: 5 years into the past, from the current point in time. This is subject to Garmin's backfill limits.

  • Polar: 30 days into the past, but not prior to the moment the user granted permission.

  • Health Connect: 30 days into the past, but not prior to the moment the user granted permission.

b. As a "pull down to refresh" functionality

As a fallback, you should implement a "pull down to refresh" functionality or alternative (like a sync now button, etc...).

Hitting this button should trigger a data pull of the last e.g. 14 days of data for the user, for all the data types you ingest.


2. Request Data via the Dashboard

You may want your customer support team to use the Terra dashboard to debug by re-sending data, or verifying whether or not Terra fetches the data correctly. See the guide below for a step by step tutorial on how to do so.


3. Request Data via the API

To request historical data from your Backend, you need to call one of the Data Retrieval Endpoints. Refer to the API endpoints section for further details on usage.

Request Usage

Refer to the API endpoints section for further details on usage.

1. Required Parameters:

To request historical data, the following request parameters are required:

  • user_id (required)

  • start_date (required)

2. Optional Parameters

Terra's Data Retrieval endpoints include many other useful and important parameters.

  1. with_samples must be set to true to receive granular data (refer toIntegration setup)

  2. to_webhook must be set to true if you want to receive data asynchronously to your Destination. For synchronous data retrieval (if your use case is time-sensitive), just set this parameter to false.

Handling Asynchronous Data Retrievals

API Request Example (Python)

Taking Python FastAPI as an example framework, you may set up your server code to look like the following:

Python
@app.post("/webhook")
async def webhook_handler(request: Request):
    payload = await request.json()
    
    if payload.get("type") == "auth" and payload.get("status") == "success":
        # Calculate date range, to get data from 28 days ago to today
        start_date = (datetime.utcnow() - timedelta(days=28)).strftime('%Y-%m-%d')
        end_date = (datetime.utcnow() + timedelta(days=1)).strftime('%Y-%m-%d')
        headers = {
            "x-api-key": os.getenv("TERRA_API_KEY"), 
            "dev-id": os.getenv("TERRA_DEVELOPER_ID")
        }
        endpoints = [
            "/activity", 
            "/daily", 
            "/sleep", 
            "/body"
        ]

        # Fetch data from each endpoint
        results = {}
        for endpoint in endpoints:
            try:
                response = requests.get(
                    f"{TERRA_API_URL}{endpoint}", 
                    headers=headers, 
                    params={
                        "start_date": start_date, 
                        "end_date": end_date,
                        "to_webhook": True
                        }
                    )
                response.raise_for_status()
                results[endpoint] = response.json()
            except requests.HTTPError as e:
                raise HTTPException(status_code=response.status_code, detail=f"Error fetching data from {endpoint}")

        return {"message": "Data fetched successfully", "data": results}
    
    return {"message": "Webhook type or status did not match criteria"}

Handling asynchronous data retrievals

When making a to_webhook=true request, keep track of the value of the terra-reference header. When the event is eventually sent to your webhook, the event's terra-reference will match that of the initial request, allowing you to mark off the data transfer as successfully completed

Request longer time ranges

Following a large request, you will receive the following:

1. "Large Request Processing" Event

You will immediately receive a Event Types event.

This indicates that Terra has acknowledged the large request and is currently processing the data retrieval from the Provider.

2. "Large Request Sending" Event

Once data retrieval has finished, Terra will organise the data into chunks, and send a Event Types payload, indicating the number of payloads to expect.

3. Chunks

When a large request is made, Terra will send the data to you in chunks of:

  • at most 10MB

  • at most 10 objects in the data array

The chunk size will be limited by whichever of the two limits gets hit first.

4. Header

ALL chunks will contain the same terra-reference header value.

Once the number of payloads indicated with the same terra-reference header value have been received, you can consider the data transfer request complete.

Requests with >28 days Time Ranges

For time ranges longer than 28 days, Terra will default to sending the data asynchronously, even if to_webhook is set to false.

This is due to the large amounts of data being transferred, which would hang the request making/handling process for >30 seconds.

Last updated

Was this helpful?