Webhooks

Webhook

Webhooks are the most basic Destination to set up, and involve Terra making a POST request to a predefined callback URL you pass in when setting up the Webhook.

They are automated messages sent from apps when something happens.

Terra uses webhooks to notify you whenever new data is made available for any of your users. New data, such as activity, sleep, etc will be normalised and sent to your webhook endpoint URL where you can process it however you see fit.

After a user authenticates with your service through Terra, you will automatically begin receiving webhook messages containing data from their wearable..

Security

Exposing a URL on your server can pose a number of security risks, allowing a potential attacker to

  • Launch denial of service (DoS) attacks to overload your server.

  • Tamper with data by sending malicious payloads.

  • Replay legitimate requests to cause duplicated actions.

among other exploits.

In order to secure your URL, Terra offers two separate methods of securing your URL endpoint

Payload signing

Every webhook sent by Terra will include HMAC-based signature header terra-signature , which will take the form:

t=1723808700,v1=a5ee9dba96b4f65aeff6c841aa50121b1f73ec7990d28d53b201523776d4eb00

In order to verify the payload, you may use one of Terra's SDKs as follows:

import os

from flask import Flask, jsonify, request
from terra.utils.verify_signature import verify_terra_webhook_signature

app = Flask(__name__)

signing_secret = os.getenv('SIGNING_SECRET')  # Your signing secret from Terra


@app.route('/webhook', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Signature')
    body = request.get_data(as_text=True)

    if signature is None:
        return jsonify({"error": "X-Signature header missing"}), 400

    try:
        is_valid = verify_terra_webhook_signature(
            payload=body, signature_header=signature, signing_secret=signing_secret
        )
        if not is_valid:
            return jsonify({"error": "Invalid signature"}), 400

        # Process the webhook data here
        webhook_data = request.get_json()
        print(f"Received valid webhook data: {webhook_data}")

        return jsonify({"message": "Webhook received successfully"}), 200

    except Exception as e:
        return jsonify({"error": str(e)}), 500


if __name__ == '__main__':
    app.run(port=8000)

IP Whitelisting

IP Whitelisting allows you to only allow requests from a preset list of allowed IPs. An attacker trying to reach your URL from an IP outside this list will have their request rejected.

The IPs from which Terra may send a Webhook are:

  • 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

Retries

If your server fails to respond with a 2XX code (either due to timing out, or responding with a 3XX, 4XX or 5XX HTTP code), requests to it will be retried with exponential backoff around 8 times over the course of just over a day.

Last updated

Was this helpful?