> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/planned-workouts-api/provider-compatibility.md).

# Provider compatibility

> ⚠️ **Pre-Release / Under Construction**
>
> This page is currently **under active development** and is provided in a **pre-release state**.
>
> Content may be **incomplete, outdated, or inaccurate**, and details may changewithout notice as the implementation evolves.
>
> Please use this documentation for **early reference only**, and avoid relying on it for production-critical decisions until the page is marked as stable.

## Provider Compatibility

Not all providers support all features. This guide helps you understand what works where.

### Handling Unsupported Features

When a feature isn't supported, Terra returns a **coercion warning** but still creates the workout:

```json
{
  "status": "success",
  "planned_workout_id": 12345,
  "coercion_warnings": [
    {
      "path": "step_blocks[0].steps[0].intensity_targets",
      "message": "Secondary targets not supported for this sport"
    }
  ]
}
```

See Coercion Warnings for details.

### Operations Support

Not all providers support all operations. The table below shows what each provider supports for creating, updating, retrieving, and deleting planned workouts.

| Operation    | Garmin | COROS | Wahoo | Suunto | TrainingPeaks | Huawei | Zepp | Hevy | Apple |
| ------------ | ------ | ----- | ----- | ------ | ------------- | ------ | ---- | ---- | ----- |
| **Create**   | ✓      | ✓     | ✓     | ✓      | ✓             | ✓      | ✓    | ✓    | ✓     |
| **Update**   | ✓      | ✓\*   | ✓     | ✓      | ✓             | —†     | ✓§   | —    | ✓     |
| **Retrieve** | ✓‡     | —     | ✓     | ✓      | ✓             | —      | —    | ✓    | —     |
| **Delete**   | ✓      | ✓     | ✓     | ✓      | ✓             | —      | ✓    | —    | ✓     |

\*COROS does not support in-place updates. Updates are performed by deleting the old workout and creating a new one.

†Huawei does not support updating workout content on the device. When you update a Huawei planned workout, only the planned date is updated in Terra's database — the workout on the device remains unchanged.

‡Garmin only returns workouts that were created by your application's API credentials. Workouts created by other apps or directly on the device will not appear.

§Zepp uses a 7-day sync window. Updates replace all workouts within the current window on the device.

**When an operation is not supported**, the API still returns a success response. For deletes, the workout is removed from Terra's database but remains on the user's device. For retrieves, only workouts stored in Terra's database are returned (not workouts from the provider).

### Quick Reference

<table><thead><tr><th width="128">Feature</th><th align="center">Garmin</th><th align="center">COROS</th><th align="center">Wahoo</th><th align="center">Suunto</th><th align="center">TrainingPeaks</th><th align="center">Huawei</th><th align="center">Zepp</th><th>Hevy</th><th>Apple</th></tr></thead><tbody><tr><td><strong>Sports</strong></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td></td><td></td></tr><tr><td>Running</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Cycling</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Swimming</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Strength</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td>✓</td><td>✓</td></tr><tr><td>Trail Running</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td>—</td><td>—</td></tr><tr><td>Mountain Biking</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr><tr><td>Backcountry Skiing</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr><tr><td><strong>Targets</strong></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td></td><td></td></tr><tr><td>Heart Rate (BPM)</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>HR % of Max</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓*</td><td>—</td><td>✓</td></tr><tr><td>HR % of Threshold</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓*</td><td>—</td><td>✓</td></tr><tr><td>HR Zones</td><td align="center">✓</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td>—</td><td>✓</td></tr><tr><td>Power (Watts)</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">—</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Power % FTP</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">—</td><td align="center">✓*</td><td>—</td><td>✓</td></tr><tr><td>Power Zones</td><td align="center">✓</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">✓†</td><td align="center">—</td><td align="center">✓†</td><td>—</td><td>✓</td></tr><tr><td>Pace</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Speed</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓*</td><td align="center">✓</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Cadence</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓¶</td><td>—</td><td>✓</td></tr><tr><td>RPE</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr><tr><td><strong>Completion</strong></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td></td><td></td></tr><tr><td>Time</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td>✓</td><td>✓</td></tr><tr><td>Distance</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td>✓</td><td>✓</td></tr><tr><td>Reps</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td>✓</td><td>—</td></tr><tr><td>Calories</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td>—</td><td>✓</td></tr><tr><td>HR Trigger</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr><tr><td>Power Trigger</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr><tr><td><strong>Structure</strong></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td align="center"></td><td></td><td></td></tr><tr><td>Multiple targets/step</td><td align="center">✓ (2, cycling/swimming)</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓ (1+cadence)</td><td>—</td><td>—</td></tr><tr><td>Block repeats</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td>—</td><td>✓</td></tr><tr><td>Exercise names</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td>✓</td><td>—</td></tr><tr><td>Swim strokes</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td>—</td><td>—</td></tr></tbody></table>

\*Converted by Terra: TrainingPeaks converts absolute values to percentages using athlete profile. Suunto, Huawei, and Zepp convert percentage targets to absolute values using provided athlete parameters or defaults.

†Zone targets converted by Terra: HR zones (1-5) and power zones (1-7) are converted to each provider's native format. HR zones use **threshold HR** as baseline for COROS and Zepp, and **max HR** for Wahoo, TrainingPeaks, Suunto, and Huawei. Power zones use FTP for all providers that support them. Output format varies: percentage (COROS, Wahoo, TrainingPeaks) or absolute BPM/watts (Suunto, Huawei, Zepp).

¶Cadence only supported as a secondary target on Zepp. Must be paired with a primary target (heart rate, power, pace, or speed).

### Provider Details

#### Garmin

**Most complete support.** Garmin devices handle nearly all workout features. Supports create, update, retrieve, and delete.

**Strengths:**

* Full strength training with exercise categories
* Swimming with stroke types and equipment
* Up to 2 targets per step (cycling/swimming)
* HR and power trigger completions
* All completion condition types

**Limitations:**

* Time-based steps inside time-based repeat blocks get unwrapped
* Exercise names must match Garmin's catalog (see Exercise Reference)
* Only one equipment item per swimming step — if multiple are provided, the first is used and a coercion warning is returned
* **Retrieve only returns workouts created by your app** — workouts created by other apps or directly on the device will not appear

**Special behaviors:**

* Single values get ±5% range applied
* HR threshold percentage converts to max HR percentage with warning
* Pool length defaults to 25m if not provided

***

#### COROS

**Good support for endurance sports.** Supports create, update (via delete + recreate), and delete. Does not support retrieve.

**Strengths:**

* Running, cycling, swimming, strength
* HR and power percentage targets
* Equipment encoded in step names

**Limitations:**

* Single target per step only (extras ignored)
* Block completion only supports REPS
* No HR/power trigger completions
* Drill stroke type not supported
* **No retrieve support** — the COROS API does not provide an endpoint to fetch existing workouts

**Special behaviors:**

* Single values get ±5% range applied
* Weight converted to grams internally
* Stroke/equipment added to step name in brackets
* Updates delete the old workout and create a new one (the provider\_workout\_id will change)

***

#### Wahoo

**Focused on cycling and running.**

**Strengths:**

* Excellent power zone support
* RPE targets
* Multiple targets per step
* Grade control for smart trainers

**Limitations:**

* No swimming support
* No strength training

**Special behaviors:**

* Percentage targets divided by 100 for API
* Single values expanded ±5%
* Steps without intensity targets get RPE fallback coercion

***

#### Suunto

**Solid multi-sport support.**

**Strengths:**

* Wide sport type support
* Swimming with stroke metadata
* Strength with exercise text
* Percentage targets converted to absolute values using athlete parameters

**Limitations:**

* Single target per step
* No controls support
* Step names truncated to 13 characters
  * Descriptions truncated to 23 characters

**Special behaviors:**

* Cadence converted from RPM to Hz (÷60)
* Manual lap trigger for open/reps completion
* Percentage targets (HR %, power %, speed %) resolved to absolute values using provided athlete parameters or defaults

***

#### TrainingPeaks

**Training platform integration.**

**Strengths:**

* RPE support
* All sports including triathlon
* Integrates with athlete profile for conversions

**Limitations:**

* Single target per step
* No stroke type support

**Special behaviors:**

* Absolute HR converted to % using athlete's max HR from request, then TrainingPeaks profile, then defaults
* Absolute power converted to % using athlete's FTP from request, then TrainingPeaks profile, then defaults
* Reps estimated as 4 sec/rep (minimum 30 sec)
* Missing profile data falls back to defaults with coercion warning

***

#### Huawei

**Running workouts only.** Supports create only. Does not support update, retrieve, or delete on the device.

**Strengths:**

* Heart rate targets (absolute BPM, max %, threshold %, zones)
* Pace and speed targets (converted to milliseconds per kilometer)
* Cadence targets (as "steps rate")
* Calorie-based completion conditions
* Block repeats via ActionCombine

**Limitations:**

* Running only — other sports get a coercion warning and appear as a run
* No power targets (running-only device)
* Single target per step (first prioritized target used)
* No strength or swimming support
* **No retrieve support** — the Huawei API does not provide an endpoint to fetch existing workouts
* **No delete support** — the Huawei API does not provide a delete endpoint. Deleting from Terra removes the record from the database but the workout remains on the user's device
* **No update support** — updates only change the planned date in Terra's database. The workout on the device is not modified
* **No planned date support** — Huawei does not support scheduling workouts for a specific date. The workout will be available on the device immediately regardless of the `planned_date` value. A coercion warning is always returned noting this.

**Special behaviors:**

* Pace stored as milliseconds per kilometer internally
* HR zones converted to absolute BPM via max HR
* Cooldown and Recovery both map to Huawei's "Relax" action with coercion warning
* Single values expanded ±5%
* Step-level reps converted to separate repeating ActionCombine blocks
* Huawei enforces unique workout names per user — duplicate names return a 400 error
* Huawei may return a 500 "createWorkout error" but still create the workout. When this happens, `provider_workout_id` will be empty and a coercion warning is returned

***

#### Zepp

**Endurance sports with a sync window constraint.** Supports create, update, and delete. Does not support retrieve.

**Strengths:**

* Running, cycling, and swimming support
* Full heart rate and power target coverage including zones and percentages
* Cadence as a secondary target alongside a primary target
* Block repeats
* Pace targets automatically converted from sec/km to m/s

**Limitations:**

* No strength training
* No swim stroke types (ignored with coercion warning)
* No equipment weight targets (ignored with coercion warning)
* No controls support
* **No retrieve support** — the Zepp API does not provide an endpoint to fetch existing workouts
* **7-day sync window** — workouts only appear on the device when scheduled within the next 7 days (today to today + 6 days). Workouts outside this window are stored in Terra but are NOT automatically pushed to the device. They will only be synced when a subsequent write or delete operation for that user triggers a window refresh. To ensure delivery, schedule workouts within the window or trigger a sync by writing/deleting any workout for the user once the date falls within range

**Special behaviors:**

* Full window replacement: every write or delete re-syncs the entire 7-day window to Zepp
* Out-of-window workouts return a coercion warning but are still stored in Terra's database
* Unsupported sports default to RUNNING with coercion warning
* Missing completion conditions default to 60 seconds
* Cadence only supported as a secondary target — if provided as the only target, a warning is returned
* Step-level reps are wrapped in repeat blocks
* Single values expanded ±5%

***

**Hevy**

Strength training routines only. Supports create and retrieve. Does not support update or delete on the provider.

**Strengths:**

* Full exercise name resolution — Garmin UPPER\_CASE names, Hevy display names, and short aliases all resolve to built-in Hevy template IDs
* Exercise metadata enrichment — custom exercises get correct muscle group, equipment category, and exercise type inferred from the shared exercise metadata registry
* Weight unit conversion (lbs to kg)
* Duration-based and distance-based sets alongside standard weight/reps

**Limitations:**

* Strength only — other sports are accepted but produce a coercion warning; the exercises are still pushed as a routine
* No heart rate, power, pace, speed, or cadence targets (not applicable to strength routines)
* No RPE support — RPE targets are silently dropped with a coercion warning
* No block repeats — each StepBlock maps to one exercise, each WorkoutStep to one set
* No planned date support — Hevy routines are not scheduled for a specific date. The routine appears in the user's library immediately regardless of planned\_date
* No delete support — -- Deleting from Terra removes the record from the database but the routine remains in the user's Hevy account
* No update support —Since routines aren't tied to a planned date, the "update planned date" operation has no effect on the provider side

**Special behaviors:**

* If the user's Hevy account hits the custom exercise limit, a 403 is returned per exercise with a coercion warning — the routine is still created with the remaining exercises
* Muscle group for custom exercises is inferred from the exercise name via the Garmin exercise→category mapping (e.g. "Bench Press" → BENCH\_PRESS → chest)

***

**Apple**

Workouts are synced via the Terra iOS SDK — the server queues actions in Redis and the SDK polls, pushes to WorkoutKit, and reports back

**Strengths:**

* Heart rate targets (absolute BPM, % of max, % of threshold, zones)
* Power targets (absolute watts, % of FTP, zones)
* Pace and speed targets
* Cadence targets
* Calorie-based completion conditions
* Block repeats via IntervalBlock iterations

**Limitations:**

* Single target per step — if multiple intensity targets are provided, only the first is used and a coercion warning is returned
* Single warmup and single cooldown per workout — Apple WorkoutKit only supports one of each. Additional warmup or cooldown blocks are dropped with a coercion warning
* No exercise names — WorkoutKit steps are defined by goals and alerts, not exercise names. Strength workouts are limited to timed interval blocks, not structured sets/reps
* No swim stroke types
* No RPE targets
* No multiple targets per step
* No retrieve support — Apple does not expose a server-side API to read scheduled workouts from WorkoutKit

**Special behaviors:**

* The SDK reports back the WorkoutKit UUID via POST /v2/plannedWorkouts/{id}/synced, stored as the provider\_workout\_id — until the SDK syncs, provider\_workout\_id will be null
* Unsupported sports (pilates, cardio, trail running, mountain biking, backcountry skiing) are mapped to the closest Apple activity with a coercion warning

***

### Best Practices

1. **Design for Garmin first** - Most complete support
2. **Use percentage targets** - Better cross-provider compatibility
3. **Check coercion warnings** - Know what was modified
4. **Test on target devices** - Verify appearance
5. **Keep step names short** - Some providers truncate


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/planned-workouts-api/provider-compatibility.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.
