Skip to main content

Hi everyone, 

I am integrating a rowing machine with Strava using FIT file uploads. During testing, I ran into two issues: 
 

VirtualRow with map

  • We would like to upload a virtual course,like Kinomap and Zwift does
  • GPS coordinates are included in the FIT-File
  • When uploading as “indoor/trainer” using the api, the map is no longer shown
  • We use the strava-v3 api for uploads

  • return new Promise((resolve, reject) => {
    api.uploads.post(
    {
    sport_type: "VirtualRow",
    // @ts-expect-error typings say Buffer, runtime wants path
    file: file, //file ref
    name,
    description,
    trainer: userSetting ? "1" : "0", //if set to 1, the gps data will not be shown.
    commute: "0",
    data_type: "fit",
    external_id: externalId // use your workoutID here
    },
    (err: any, payload: any) => {
    if (err) return reject(err);
    resolve(payload);
    }
    );
    });

    👉 Question: How should the upload be structured so that Strava recognizes it as a virtual activity and still shows the map?

Timestamps with GPS data

  • Once GPS/track data is included, Strava always uses the timestamps from the GPS coordinates.
  • The actual timestamp provided in the FIT file is ignored.

  • 👉 Question: Is there a specific FIT field or recommended way to ensure Strava respects the intended timestamp instead of forcing GPS-based timestamps? Is this related to question 1 ? 

One more hint, we do set the Sport-Information in the session-message:
 

sessionMesg.setSport(Sport.ROWING);
sessionMesg.setSubSport(SubSport.INDOOR_ROWING);

Has anyone successfully solved this for rowing (or similar virtual setups)? Example FIT snippets would be highly appreciated.

What happens when you upload the activity without the trainer flag?


Great question - just tested: 
 

TEST Workout - API call without “trainer”

If I omit the optional trainer flag, the GPS data is displayed (although the timestamp issue remains).
However, when I edit this workout in Strava, the Indoor flag is not set automatically. If I manually set it, the map disappears.

For now, I could live with ignoring this behavior. But I would like to clarify:

Is Strava actually expecting that all virtual/indoor activities must be flagged this way (and therefore not show a map), or is it acceptable to upload them without the trainer flag so the map remains visible?


GPS Data:

The indoor flag is used to indicate an activity on a non-smart indoor trainer (bike trainer, treadmill, stationary bike, etc) so the assumption is that there is no GPS data associated with it.

 

The virtual activity types (virtual ride, virtual run, virtual rowing) are assumed to be on smart devices which have embedded GPS data and emulate real world conditions. They do not have the indoor flag set (virtual implies indoor).

 

The correct thing to do is upload the activity with sport_type = VirtualRow and not set the indoor flag.

 

Timestamps

Are you saying you want it to use the timestamp associated with the record entry itself instead of the timestamp field in the record? Is there a reason you can’t set the two values to be equal?

 


Thanks, that clarifies the trainer vs. virtual handling – that helps a lot.
I will then ommit the trainer flag happily. 

Regarding the timestamps:
What we see is that Strava seems to apply the timezone of the GPS coordinates instead of the actual timestamps in the records.

Example:

  • The user performs the workout physically in Germany at 2025-09-17 18:00 CET.

  • If the simulated virtual track is also in Germany, Strava displays the correct start time.

  • But if the very same workout simulates a track in Bali, then Strava shifts the start time to 2025-09-17 23:00 WITA (Bali local time).

So even though the FIT file contains the correct German timestamps, Strava appears to override them based on GPS location.

👉 Is there a way to ensure Strava respects the timestamps as written in the FIT records, instead of inferring timezones from the GPS coordinates?