For the complete documentation index, see llms.txt. This page is also available as Markdown.
Quickstart
Learn how to receive data events in just 3 steps
2 minute video walkthrough of Quickstart
Key steps to setup Unified API
Follow this short tutorial to set up event-based health data delivery via Webhooks. Learn how Terra manages user authentication and can automatically send new user data, simplifying your integration. (Other methods, like requesting historical data, are covered in the detailed guides.
1
Integration Setup
A. Add Data Sources from your Terra Dashboard
First you need to select your data sources on your Terra dashboard. This determines:
(a) What data sources are available for end-users to chose on the Terra auth widget.
What data sources are automatically synced to your data destination via events.
B. Add a Data Destination in your Terra Dashboard
The Unified API is event-based, so the DataDestinations are where you will receive payload events:
(a) New health data updates
(b) Authentication events, de-auth events, etc.
How to setup a Webhook destination?
Webhook.site
Using webhook.site you can generate a temporary webhook destinations for testing.
Copy Your unique URL that is automatically generated when you enter the site.
Your own Webhook endpoint on your local machine
First create a web server that runs locally on your computer (see code block).
Then, expose your server to the internet with a tool such as ngrok and start receiving payloads.
If you are using ngrok, running ngrok http {PORT_NUMBER} will expose your server to the internet and return its URL.
C. Obtain your API Key & Dev-ID from your Terra Dashboard
Screenshot of the Terra dashboard with a red box highlighting the button to obtain API credentials
Core concept: `user_id`
All data is linked back to a user_id on Terra's side. This uniquely identifies a wearable account connection through the API and allows you to retrieve data for that wearable account. This is what Terra calls a User (Terra user).
You will use this user_id in all your data-related interactions with Terra
Core concept: `reference_id`
You can link a user_id to an entity on your end using a reference_id. This is a custom identifying metadata you can define on the Terra User object to link them back to a user on your app.
2
User Authentication
Next you need to authenticate a user via the API to a data source (e.g. to Oura, Fitbit, Withings).
Terra simplifies this by allowing you to generate a pre-built authentication widget session (by running the following code).
Copy/Paste the widget session url into web browser. To test the authentication flow, you can choose a data sources (e.g. Fitbit), and complete the flow.
3
Receive data updates
Terra automatically sends new data to your server (e.g. webhook endpoint) when it becomes available from your users' wearables.
If you're using your own Webhook destination, the following code is an example of how you can handle Webhooks.
4
Example payloads
temperature_data can carry two kinds of temperature reading. delta is the deviation of the user's skin temperature from their personal baseline, in °C, sent by sources that compute their own baseline (e.g. Oura, Fitbit, Garmin). avg_skin_temperature_celsius is the average absolute skin temperature in °C measured over the sleep session, sent by sources that report an absolute reading (e.g. WHOOP). A sleep record contains whichever field the user's device reports; the other is null.
Next steps
Now that you understand the basics, move onto onto our guides for detailed documentation on the Unified API
import logging
import flask
from flask import request
logging.basicConfig(level=logging.INFO)
_LOGGER = logging.getLogger("app")
app = flask.Flask(__name__)
@app.route("/consumeTerraWebhook", methods=["POST"])
def consume_terra_webhook() -> flask.Response:
data = request.get_json()
_LOGGER.info(
"Received webhook for user %s of type %s",
data.get("user", {}).get("user_id"),
data["type"]
)
# you can now use the incoming data in your app
# handleData(data)
if __name__ == "__main__":
app.run(host="localhost", port=8000)
javascript
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
// Parse raw JSON bodies
app.use(
bodyParser.raw({
inflate: true,
limit: "4000kb",
type: "application/json",
})
);
// Webhook endpoint
app.post("/consumeTerraWebhook", (req, res) => {
res.sendStatus(200); // Respond to Terra immediately
try {
const data = JSON.parse(req.body.toString("utf8"));
console.log("Received Terra Webhook Data:");
console.log(JSON.stringify(data, null, 2));
} catch (err) {
console.error("Failed to parse webhook payload:", err.message);
}
});
// Start server
const port = 3000;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
})