Terra now delivers per-set strength training data

Why strength training was the blind spot of health data
In the data models that we published, a strength workout was one entry in an enum (that is, a fixed list of possible values) consisting of over a hundred items, together with the amount of energy burned and the strain level. This meant that an hour of squats and a 10k run resulted in payloads of the same form.
Customers whose users carried out lifts using a dedicated strength app, kept asking us "can workouts please include exercises, reps, weight, including volume (kg), series/sets besides HR and distance?". The demand is also evident from usage figures. This year, multiple of our fastest-growing customers are strength-first training platforms, and its data throughput increased by 350%+ per month, even though at that time we had no structured lifting data to provide it.
We've since launched these new data types, including 6 new strength-related integrations!
What's in the strength_data payload
Strength data appears as a new strength_data item on the activity payload which you already receive, so it does not introduce a new endpoint or a new method of delivery. When doing a run or a ride, the item is null.
In there, each workout is divided into exercises and each exercise is broken down into sets. A set includes the number of repetitions, the weight in kilograms, a load type (further details of which will be given below), the duration, and the rest time that follows it. Whenever the source gives information about the effort, this is also included: the RPE (which stands for rating of perceived exertion and is a score from 1 to 10 indicating how hard the set felt to the lifter) and the RIR, which stands for reps in reserve and means the number of additional repetitions that were still left.
Sets are also given types, which means that a warm-up can be told apart from a working set, from a dropset (which involves reducing the weight during the exercise and then continuing), and from a set taken to failure. Exercises have both a main and a secondary muscle group, with them being kept separate since a bench press is exercise for the chest that also places a demand on the triceps and shoulders, and if the two lists were combined it would imply that the athlete trained the chest and the triceps equally.
A group id indicates supersets, which are exercises carried out one after another without any rest.
It comes with nine integrations. Eight of these are logging applications: Fitbod, Hevy, Strong, StrongLifts, Liftosaur, Lyfta, wger, and TrainingPeaks. The ninth is Garmin, with the sets being provided by the watch.
How Terra normalizes exercises: movements plus modifiers
The simplest method of standardizing the exercises across the nine sources is to draw up a long list of entries. We created that initial list, which consisted of about 2,400 entries, and the way it failed influenced the design that we ultimately shipped.
The model we shipped considers an exercise to be a movement combined with some modifiers. There are 174 published movements and thirteen modifier axes which cover various aspects such as the implement (for example, barbell, dumbbell, kettlebell, machine), the grip, the stance, the tempo, and whether the exercise is performed on one limb. "Pause Bench Press" is simply a bench press with a tempo modifier attached. It is not necessary for anyone to have previously declared the combination for the exercise to remain intact.
Certain of the rules required a good deal of judgement: a jump squat is a squat with an explosive pace since it lands where it began, whereas a box jump is a separate movement because it doesn't. Prior to this rule being introduced, the three variants of the Bulgarian split jump were classified in different ways depending on who had produced the map, and a query regarding squat volume had found one of the three.
If an exercise doesn't match anything that we have a mapping for, then we keep it; the source's label is copied exactly as it is, and the movement fields remain empty, thus ensuring that nothing which a lifter has logged is ever discarded. Simply dropping exercises that can't be classified would only rekindle the flat-list bug.
Terra doesn't assign canonical exercise IDs
In an earlier version of the model a Terra exercise ID was generated, with one canonical key for each exercise, and this was deleted before the release was made; the schema (the published field-by-field definition of the payload) still includes the reserved field in the place where it previously was.
The reason (and I believe this is the most interesting design choice in the entire feature) is that whether or not two exercises are "the same" depends on the person making the determination. A rehabilitation tool is concerned that the grip has changed between two sets of rows, whereas a volume tracker doesn't give a damn. A single Terra-minted ID would have imposed one rule on both situations and the rule would have appeared authoritative even though it involved a matter of judgement. Moreover, any subsequent revision of that judgement would have quietly altered the meaning of the historical data.
In place of an ID you obtain the various parts, the movements and the thirteen axes, and then you formulate the equality that applies to your product, which implies that two different products can differ as to what constitutes the same exercise and yet both can be correct.
The discipline is also evident in smaller instances: if a modifier is missing then it is because the source failed to include it, not because a default has been applied, and an automated test as part of our build pipeline ensures that the absence is never substituted with a value.
A modifier axis exists with the function of alerting you to the numbers: the accommodating_resistance flag indicates that bands or chains are being used on the bar, and this means that the recorded weight does not reflect the actual load at the top of the lift. With regard to load type there is a noted limitation in that only those sets marked as external should be included when calculating training volume (tonnage, which is the total of the number of repetitions multiplied by the weight), since blindly adding up all the sets would result in assisted work being counted twice and in an incorrect interpretation of bodyweight exercises that are weighted. The schema states this in its own comments.
Strength sets from a Garmin watch without any guesswork
While the eight logging apps show what the lifter entered on their phone, Garmin is different in that its sets are derived from the watch itself. This distinction is evident throughout the entire design.
The detailed information for each set is included in the FIT file (the binary format used by fitness devices to record activities), and we analyse it directly. The exercise classifier on the watch suggests possible exercises with a confidence level, and we only accept the top suggestion when the confidence is non-zero; if the confidence is zero, the exercise remains unresolved rather than being assigned a plausible exercise name.
Weight called for a decision of its own: Since a watch cannot measure load, any weight displayed on a Garmin device is a figure the lifter has entered, and in reality, lifters do not type in their own body weight. A push-up with no recorded weight thus ends up with load_type set to bodyweight instead of being assigned a zero load, thanks to a documented fallback procedure. Part of the process is simply administrative: a single "set" covering the whole of a 55-minute activity is recognised as failed rep detection and is then discarded.
Since the data that has been logged and the data that has been sensed are now placed beside each other, each exercise is given a source label which is either device_detected or user_logged. Only the latter has been confirmed by the user. However, you can make use of this in the way you choose; for instance, you could automatically fill in a workout log using the watch and then ask the user to confirm it, or you could ensure that personal-record detection is based only on confirmed sets while allowing streaks and adherence to be based on the sensed data.
What you can build with per-set strength data
To be clear, these are possibilities, ideas which the fields support rather than features that we ship; yet it is because of them that the fields exist.
The most convincing of these is plateau detection based on effort. A lifter who lifted 100 kg for five repetitions at an RPE of 9, the same set having been performed at an RPE of 7 six weeks earlier, is now showing signs of stagnation, and all the figures required to detect this are included in the payload. With the previous system that used a flat payload, that session could not be distinguished from the easiest week of that lifter's life.
Set types also make volume accounting more honest since you can exclude warm-ups from the weekly total and treat failure sets and AMRAP sets (as many reps as possible) as the high-stimulus activities they are. By having separate lists for primary and secondary muscles, a recovery model can assign most of the weight of a bench press to the chest and a small amount to the triceps, which is exactly what a per-muscle training-load model is based on, rather than using whole-body calorie estimates.
There is also the bodyweight boundary, at which progression tracking typically breaks. Since the weight carried is associated with the set and not with the name of the exercise, an assisted pull-up and a pull-up with 20 kg hung from a belt are considered to have the same identity as the simple bodyweight version, meaning the entire progression from assisted to weighted versions can be recorded on a single chart.
When it comes to physio and rehab products, the useful item is the single-limb modifier. In the flat list, the only reference to single-limb work was the substring "Single Leg" located somewhere in the name of an exercise. The modifier is applied to all movements at the same time, which means that you can retrieve all of a user's single-limb exercises with a single query and observe the left-right loading during a return-to-play phase (that is, the supervised training period following an injury).
How to get access to strength_data
strength_data is set up on a per-account basis and is additive in that nothing in your current payloads will change until it has been turned on. Once it has been enabled, historical strength workouts can be obtained via the standard historical data request, and sets will arrive a little after the rest of the activity since they are included in the FIT file. If you'd like it on your account, you should contact us!








