For Coaches Coaching workflows

Exporting workouts to TrainingPeaks and Garmin

Push a planned workout from the Hub to TP (ZWO) or a Garmin/Wahoo head unit (FIT).

Two formats, two destinations

The Hub can emit a planned workout as either:

Both downloads live on the workout detail page, under Export workout.

What's confirmed working

After the 2026-05 import bisect:

What was broken and got fixed

We previously emitted a <category>Cycling</category> element that TP rejected with "We currently only support power based cycling workouts in ZWO format." It turns out <category> is not part of the Zwift ZWO schema — Zwift itself never emits it. Removing it was the cure. The exporter now emits files in the canonical Zwift order: author → name → description → sportType → tags → workout.

If you ever see that rejection again, it means a regression has crept back into core/services/zwo_export.py. The regression test test_no_category_element guards against that.

What doesn't work yet (intentional)

How to test new variants yourself

We keep a bisect probe suite in docs/zwo_test_suite/ (14+ files) that tests specific ZWO features against TP's import path. If you want to confirm that, say, a new <FreeRide> block or a MaxEffort marker imports correctly, generate the probes (python manage.py emit_zwo_test_suite) and drop the files into TP one by one. The README in that folder explains the workflow.

Last updated May 13, 2026

Still stuck? Ask us a question and we'll write up an answer.

Ask a question