# Health Rewards

## Health Rewards

### Overview

The **Terra Health Rewards** product lets you turn the raw activity, sleep and physiological data you already receive through the Terra API into **actionable, gamified points** that drive user engagement.

* **Science‑based & adaptive** – Points are calculated from evidence‑backed metrics (sleep duration, HRV, steps, floors climbed and more) and automatically adjust to each individual’s baseline.
* **Real‑time** – Rewards are generated on demand
* **Configurable** – Limits, category weights and streak bonuses can be tweaked in **Dashboard → Health Rewards** (see screenshots below).
* **Monetisable** – Combine earned points with in‑app currency, coupons or badge systems to incentivise healthier habits.

<figure><img src="/files/bFQqvkxY08c3x3wKLXgX" alt=""><figcaption></figcaption></figure>

***

### How It Works

1. **Enable Rewards**\
   \&#xNAN;*Open the dashboard, navigate to **Health Rewards** and toggle the product to “Enabled”.*\
   Here you can:
   * assign **daily point caps** (overall or per category),
   * choose **weights** for each goal (e.g. “Hours Slept = 3 pts”, “Steps = 1 pt”),
   * add **streak bonuses** (e.g. “≥10 pts 2 days in a row → +1 pt”).\
     All changes apply instantly to new calculations.
2. **Request points**\
   Call the Rewards endpoints (see below) providing the *user\_id* and a *start\_date* (and optionally *end\_date*).\
   Terra fetches the necessary `daily`, `sleep`, `activity`, data, runs the algorithm in real time, then returns a **total** plus a **human‑readable breakdown** for every day.

***

### Endpoints

> Base URL `https://api.tryterra.co/v2`\
> All calls require the standard `dev-id` & `x-api-key` headers.

| Method | Path                            | Purpose                                            |
| ------ | ------------------------------- | -------------------------------------------------- |
| `GET`  | `/rewards/points`               | Calculate points for a period                      |
| `POST` | `/rewards/points/spent`         | Deduct points (e.g. when a user redeems a voucher) |
| `GET`  | `/rewards/points/spent/history` | Retrieve a chronological list of redeemed points   |

#### 1 Get points

```http
GET /rewards/points?user_id=USER123&start_date=2024‑08‑01&end_date=2024‑08‑07&store=true
dev-id: YOUR_DEV_ID
```

**Query parameters**

| Name         | Type         | Required | Description                                         |
| ------------ | ------------ | -------- | --------------------------------------------------- |
| `user_id`    | string       | ✓        | Terra user identifier                               |
| `start_date` | `YYYY‑MM‑DD` | ✓        | First date (inclusive)                              |
| `end_date`   | `YYYY‑MM‑DD` |          | Last date (exclusive). Defaults to start\_date + 1. |

<details>

<summary><strong>Successful response (200)</strong></summary>

```json
{
  "status": "success",
  "total": 147,
  "daily": [
    {
      "date": "2024-08-06",
      "raw_total": 12,
      "breakdown": {
        "sleep": {
          "streaks": [
            {
              "achieved": true,
              "goal": "Achieve 3 sleep points or more for at least 2 consecutive days",
              "points": 1,
              "max": 1
            }
          ],
          "raw_total": 4,
          "hours": {
            "achieved": 8,
            "goal": "Achieve 7.0-9.0 hours in bed",
            "points": 3,
            "max": 3
          },
          "bedtime": {
            "achieved": "11:00 PM",
            "goal": "Go to bed between 10:10 PM and 11:10 PM",
            "points": 2,
            "max": 2
          },
          "efficiency": {
            "achieved": 95,
            "goal": "Achieve a sleep efficiency of 88% or higher",
            "points": 2,
            "max": 2
          },
          "quality": {
            "achieved": 69,
            "goal": "Achieve a sleep quality of 77% or higher",
            "points": 0,
            "max": 2
          },
          "max": 4
        },
        "movement": {
          "floors": {
            "achieved": 0,
            "goal": "Achieve 3 floors climbed",
            "points": 0,
            "max": 1
          },
          "steps_proportional": {
            "achieved": 7266,
            "goal": "Achieve up to 10000 steps",
            "points": 1,
            "max": 2
          },
          "streaks": [
            {
              "achieved": false,
              "goal": "Achieve 2 movement points or more for at least 2 consecutive days",
              "points": 0,
              "max": 1
            }
          ],
          "raw_total": 1,
          "steps": {
            "achieved": 7266,
            "goal": "Achieve 10000 steps",
            "points": 0,
            "max": 1
          },
          "floors_proportional": {
            "achieved": 0,
            "goal": "Achieve up to 3 floors climbed",
            "points": 0,
            "max": 1
          },
          "max": 2
        },
        "streaks": [
          {
            "achieved": true,
            "goal": "Achieve 10 points or more for at least 2 consecutive days",
            "points": 1,
            "max": 1
          }
        ],
        "health_data": {
          "resting_heart_rate": {
            "consistency": {
              "achieved": 74,
              "goal": "Achieve a resting heart rate of 81 or lower",
              "points": 1,
              "max": 1
            },
            "improvement": {
              "achieved": 74,
              "goal": "Achieve a resting heart rate of 66 or lower",
              "points": 0,
              "max": 1
            }
          },
          "streaks": [
            {
              "achieved": true,
              "goal": "Achieve 1 health data points or more for at least 2 consecutive days",
              "points": 1,
              "max": 1
            }
          ],
          "raw_total": 1,
          "max": 1,
          "hrv": {
            "consistency": {
              "achieved": 22,
              "goal": "Achieve an HRV of 23 or higher",
              "points": 0,
              "max": 1
            },
            "improvement": {
              "achieved": 22,
              "goal": "Achieve an HRV of 28 or higher",
              "points": 0,
              "max": 1
            }
          }
        },
        "activity": {
          "streaks": [
            {
              "achieved": true,
              "goal": "Achieve 3 activity points or more for at least 2 consecutive days",
              "points": 1,
              "max": 1
            }
          ],
          "raw_total": 8,
          "target": {
            "achieved": {
              "moderate": 22,
              "vigorous": 44
            },
            "goal": "Achieve 30 minutes of moderate or 15 minutes of vigorous activity",
            "points": 5,
            "max": 5
          },
          "max": 8,
          "extra": {
            "achieved": {
              "moderate": 22,
              "vigorous": 44
            },
            "goal": "Achieve up to 15 extra minutes of moderate or 8 extra minutes of vigorous activity",
            "points": 2,
            "max": 2
          },
          "proportional": {
            "achieved": {
              "moderate": 22,
              "vigorous": 44
            },
            "goal": "Achieve up to 30 minutes of moderate or 15 minutes of vigorous activity",
            "points": 5,
            "max": 5
          }
        }
      },
      "streak_total": 4,
      "max": 12
    }
  ]
}
```

</details>

Key fields:

| Field                   | Description                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `total`                 | All‑time points earned (including streak bonuses, minus redemptions).                                             |
| `daily[*].raw_total`    | Points *before* streak bonuses that day.                                                                          |
| `daily[*].breakdown`    | Per‑category goals (activity, sleep, movement, health\_data) with **goal**, **achieved**, **points** and **max**. |
| `daily[*].streak_total` | Points awarded from streak goals for that day.                                                                    |

#### 2 Spend points

```http
POST /rewards/points/spent?user_id=USER123
dev-id: YOUR_DEV_ID
Content-Type: application/json

{ "points": 50 }
```

*Deducts 50 points from the user’s balance. A 400 error is returned if the user has insufficient points.*

#### 3 Redemption history

```http
GET /rewards/points/spent/history?user_id=USER123&start_date=2024‑01‑01&end_date=2024‑12‑31
dev-id: YOUR_DEV_ID
```

Returns an ordered array `[ [points, timestamp] ]`.

***

### Response Object Anatomy

Below is a trimmed version of the example response highlighting the structure you will typically work with:

```json
{
  "daily": [
    {
      "date": "2024‑08‑06",
      "breakdown": {
        "activity": {
          "proportional": { "goal": "Up to 30 mins", "achieved": {...}, "points": 5, "max": 5 },
          "target":       { "goal": "30 mins",        "points": 5 },
          "extra":        { "goal": "Extra 15 mins",  "points": 2 },
          "streaks":      [ { "goal": "≥3 activity pts for 2 days", "points": 1 } ],
          "raw_total": 8,
          "max": 8
        },
        "sleep":   { … },
        "movement":{ … },
        "health_data": { … }
      },
      "raw_total": 12,
      "streak_total": 4,
      "max": 12
    }
  ],
  "total": 147
}
```

> **Tip – Parsing points quickly**\
> If you only need the numeric score, read `daily[*].raw_total + daily[*].streak_total`.\
> If you want to visualise goals, iterate over `breakdown` and use the `goal` / `achieved` strings to populate the UI.

***

### Dashboard Configuration

The Health Rewards UI (see screenshots) is laid out by **category**:

| Category        | Example Goals                                          |
| --------------- | ------------------------------------------------------ |
| **Activity**    | Minutes of moderate / vigorous activity                |
| **Movement**    | Steps & floors climbed                                 |
| **Sleep**       | Hours in bed, bedtime consistency, efficiency, quality |
| **Health Data** | HRV, resting heart‑rate consistency & improvement      |

Use **Limits & Streaks** to:

* Set an **overall cap** (e.g., 30 pts / day)
* Add **global streaks** (e.g., ≥20 pts for 5 days → +3 pts)
* Define **per‑category streaks** (e.g., Movement ≥5 pts for 3 days → +1 pt)

All configuration is stored in Terra and read by the API at calculation time.

***

### Example Use Case – “Weekly Wellness Challenge”

1. **Configure Goals**
   * Dashboard → Health Rewards
   * Overall daily limit = 30 pts
   * Activity proportional = max 5, target = 5, extra = 2
   * Movement steps = 1, proportional = 2
   * Sleep hours/efficiency/quality = 2 each
   * Add streak: ≥20 pts for 7 days → +5 bonus
2. **Frontend Implementation**
   * Show a progress bar that calls **GET /rewards/points** every morning for yesterday’s date.
   * Display breakdown tool‑tips using the `goal` and `achieved` strings.
3. **Redemption Flow**
   * When a user taps “Redeem 100 pts for free shipping”, call **POST /rewards/points/spent**.
   * Show the new balance (`total` field) returned in the 200 response.
4. **Leaderboard**
   * Aggregate `raw_total + streak_total` per user over the week to show top performers.

***

### Best Practices

* **Sync ahead of time** – Make sure wearable data is pulled **before** you calculate rewards for a day.
* **Store on server‑side** – Use `store=true` (default) so that the canonical balance lives with Terra and cannot be tampered with client‑side.
* **Handle nulls gracefully** – If a metric is missing (e.g., HRV), its goal will remain but `points` might be `0`.
* **Rate limits** – Reward endpoints share the same rate limits as other `v2` calls (60 req/min default). Aggregate user calls where possible.

***

### FAQ

| Question                                      | Answer                                                                                                           |
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| **Can I backfill rewards?**                   | Yes. Provide a historical `start_date`/`end_date`; Terra will fetch past data and compute points retro‑actively. |
| **What time zone are dates evaluated in?**    | All dates are interpreted in **local time**.                                                                     |
| **Can I override an individual user’s goal?** | Not yet. Goals are global per developer account.                                                                 |
| **Why are my users getting 0 points?**        | Check that the necessary data (sleep, daily summary) exists and that rewards are enabled for your dev ID.        |

***

Need help? Reach out via a dashboard support ticket.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tryterra.co/health-rewards.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
