TriPeak

The upload API

TriPeak connects directly to Garmin and Wahoo. Every other device exports a FIT file, and this is where that file goes: one POST, one bearer token, and the session lands on the plan matched, priced and graded exactly as a synced one would. It exists so that apps like HealthFit can offer TriPeak as a destination without an OAuth application, a partner agreement or a meeting.

The request

Method and URL
POST https://tripeak.app/api/upload/fit
Authentication
Authorization: Bearer <upload token>. Also accepted: an X-Upload-Token header, or ?token= in the query.
Body
The FIT file bytes as the request body (any Content-Type), or a multipart/form-data request with the file in any field.
Optional
X-File-Name: the original file name, kept on the session.
Limits
25 MB per file. FIT only — .tcx and .gpx are accepted in the app by drag and drop, not here.

The token

Each athlete has one upload token, shown under Connections in TriPeak. It names that athlete and can do one thing: add their recordings. It is not their sign-in and not their share link. The athlete can regenerate it at any time, which stops the old one at once — an app should treat a 401 as “ask the athlete for the current token”, not as a transient error.

What happens to the file

The reply

JSON, always. 200 with ok: true when the file was processed; an error field otherwise.

outcome
"matched" (filled in the planned session), "extra" (added as an unplanned session), "updated" (this file had been uploaded before; refreshed), or "duplicate" (the same recording was already there from another source; nothing added).
session
The session it landed on: id, title, date, sport, status, planned_tss, completed_tss, is_unplanned, and a url that opens it in TriPeak.
external_id
How TriPeak identifies this recording: "upload-" followed by the start time in milliseconds. Sending the same file again updates rather than duplicates.
tss, intensity_factor, sport, date
What the file was priced at, and the day it was filed under (the watch’s local day where the file carries one).
recording
"stored" when the streams were kept.

Errors

401
No token, or a token that is not current. Ask the athlete for the token shown under Connections.
400
No file in the request.
413
Over 25 MB.
415
Not a FIT file.
422
The file could not be read, or holds under thirty seconds of recording.
405
Anything but POST.

Examples

curl: curl -X POST https://tripeak.app/api/upload/fit -H "Authorization: Bearer tpu_…" -H "X-File-Name: ride.fit" --data-binary @ride.fit

Multipart: curl -X POST https://tripeak.app/api/upload/fit -H "Authorization: Bearer tpu_…" -F "file=@ride.fit"

Apple Shortcuts: Get Contents of URL → POST → Request Body: File → Headers: Authorization = Bearer <token>. Trigger it from the Workout automation or from the share sheet.

For app developers

If you make an app that exports workouts and would like TriPeak listed as a destination, this is the whole integration: store the athlete’s token, POST each new FIT file, show them the url from the reply. Idempotent by file, one round trip, no refresh tokens. Write to hello@tripeak.app for a test account and token, or if you need anything changed — a JSON body, a different auth header, TCX — it is a small endpoint and can move.

TriPeak is triathlon coaching software for coaches and self-coached athletes: structured sessions scored in TSS, fitness and form tracking, Garmin sync with execution grading, and an MCP server so Claude or ChatGPT works with the real plan.

See how it works