Data models
📘 Note
All fields in all models are nullable unless explicitly stated otherwise.
🚧 Uniquely identifying payloads
Activity & Sleep
Activity & Sleep payloads can be uniquely identified by their
summary_idfield undermetadata. If an activity comes in a second time, with the same summary ID, you should update the previous entries with the new data corresponding to thatsummary_idBody, Daily, Nutrition
Body, Daily, Nutrition payloads can be uniquely identified by the combination of their
start_timeandend_timefields undermetadata. If one of these payloads comes in again, with the samestart_timeandend_time, you should update the previous entries with the new data.For example, the
Dailypayload can come in multiple times in one day, with updatedstepsfield every timeHormone
Hormone payloads can be uniquely identified by their timestamp field (at the top level of each entry, not under metadata, since Hormone has no metadata wrapper). If a hormone payload comes in again with the same timestamp, you should update the previous entry with the new data.
🚧 Schema parser
When building a parser for the models below, please take into account that more fields may be added down the line (but no field name should ever change within a given version)
Also note that this version is equivalent to
2022_03_16
TerraUser
{
"user_id": String, // not nullable
"provider": String, // not nullable
"last_webhook_update": String,
"scopes": String,
"reference_id": String
}Core data types
Activity
StrengthExercise
An exercise is one or more movements plus a set of modifiers, not a single name from a fixed list — a paused squat is movements: ["squat"] with modifiers.tempo: "paused". Match on movements to group work by pattern; read modifiers when the variant matters.
An exercise with an empty sets array is one the user put in the workout and recorded nothing against — it happened, the per-set detail did not. sets is [] in that case, never null.
An unset modifier arrives as null and means the source did not report that axis — not that the exercise was bilateral, or barbell, or full range. movements and the muscle arrays are null rather than [] when unresolved, so null-check before iterating. modifiers itself is null when the source reports no axis at all.
movements is empty when the exercise could not be resolved — most often a coach-written or user-created exercise the source names but does not classify. exercise_name still carries the source's label, so display keeps working even when matching does not:
exercise_name is passed through verbatim and its shape follows the source. A training app sends what the user sees (Close Grip Bench Press); a wearable sends its own catalogue key (triceps_pressdown). Never parse it — use movements and modifiers for logic and exercise_name for display.
source, set_type, load_type and the muscle arrays fall back to unknown rather than being omitted when the source reported something that could not be resolved.
primary_muscles is the focus of the exercise and secondary_muscles the work it also involves. They are kept apart because merging them would say a bench press trained chest and triceps equally. How specific they are varies by source.
Two shapes to allow for:
A whole-body lift — an olympic lift, a loaded carry, a burpee — reports every muscle it works as primary, with
secondary_musclesempty, because no single muscle is the focus.An exercise can report secondary muscles with no primary. Code that iterates
primary_musclesalone will miss that work.
StrengthSet
weight_kg is meaningless without load_type. Only external means the weight is load added to an otherwise unloaded body. Summing weight_kg × reps across all sets overstates volume, because it counts bodyweight and assistance as if they were added plates.
Test for external rather than against the other values — a load type you don't recognise must be treated as unknown, not as external.
Athlete
Body
Daily
Hormone
Menstruation
Nutrition
Sleep
Enums
DeviceDataType
Represents data types that a certain device contributed to
Steps
STEPS
Active minutes
ACTIVE_MINUTES
BMR
BMR
Calories
CALORIES
Distance
DISTANCE
Heart Rate
HEART_RATE
Oxygen Saturation (SpO2)
OXYGEN_SATURATION
Sleep type classification
SLEEP_TYPE
Speed
SPEED
Cadence
CADENCE
AFibFlag
Negative (AFib not present)
0
Positive (AFib present)
1
Inconclusive
2
VisceralFatCategory
Health-risk classification derived from visceral_fat_level using provider-specific thresholds. Null when thresholds are not available for the provider.
Normal
normal
High
high
Very High
very_high
ActivityType
In Vehicle
0
Biking
1
Still
3
Unknown
4
Tilting
5
Walking
7
Running
8
Aerobics
9
Badminton
10
Baseball
11
Basketball
12
Biathlon
13
Handbiking
14
Mountain Biking
15
Road Biking
16
Spinning
17
Stationary Biking
18
Utility Biking
19
Boxing
20
Calisthenics
21
Circuit Training
22
Cricket
23
Dancing
24
Elliptical
25
Fencing
26
American Football
27
Australian Football
28
English Football
29
Frisbee
30
Gardening
31
Golf
32
Gymnastics
33
Handball
34
Hiking
35
Hockey
36
Horseback Riding
37
Housework
38
Jumping Rope
39
Kayaking
40
Kettlebell Training
41
Kickboxing
42
Kitesurfing
43
Martial Arts
44
Meditation
45
Mixed Martial Arts
46
P90X Exercises
47
Paragliding
48
Pilates
49
Polo
50
Racquetball
51
Rock Climbing
52
Rowing
53
Rowing Machine
54
Rugby
55
Jogging
56
Running On Sand
57
Treadmill Running
58
Sailing
59
Scuba Diving
60
Skateboarding
61
Skating
62
Cross Skating
63
Indoor Rollerblading
64
Skiing
65
Back Country Skiing
66
Cross Country Skiing
67
Downhill Skiing
68
Kite Skiing
69
Roller Skiing
70
Sledding
71
Snowboarding
73
Snowmobile
74
Snowshoeing
75
Squash
76
Stair Climbing
77
Stair Climbing Machine
78
Stand Up Paddleboarding
79
Strength Training
80
Surfing
81
Swimming
82
Swimming In Pool
83
Open Water Swimming
84
Table Tennis
85
Team Sport
86
Tennis
87
Treadmill
88
Volleyball
89
Beach Volleyball
90
Indoor Volleyball
91
Wakeboarding
92
Walking Fitness
93
Nording Walking
94
Walking Treadmill
95
Waterpolo
96
Weightlifting
97
Wheelchair
98
Windsurfing
99
Yoga
100
Zumba
101
Diving
102
Ergometer
103
Ice Skating
104
Indoor Skating
105
Curling
106
Other
108
Crossfit
113
HIIT
114
Interval Training
115
Walkin Stroller
116
Elevator
117
Escalator
118
Archery
119
Softball
120
Guided Breathing
122
Cardio Training
123
Lacrosse
124
Stretching
125
Triathlon
126
INLINE_SKATING
127
SKY_DIVING
128
PADDLING
129
MOUNTAINEERING
130
FISHING
131
WATER_SKIING
132
INDOOR_RUNNING
133
PADEL_TENNIS
134
DRIVING
135
OFF_ROAD_DRIVING
136
MOTORBIKING
137
MOTOR_RACING
138
ENDURO
139
CANOEING
140
ORIENTEERING
141
HANG_GLIDING
142
FLYING
143
HOT_AIR_BALLOONING
144
JET_SKIING
145
POWER_BOATING
146
GAELIC_FOOTBALL
147
HURLING
148
TRAIL_RUNNING
149
GRAVEL_CYCLING
150
MULTISPORT
151
E-BIKING
152
E MOUNTAIN BIKING
153
PHYSICAL_THERAPY
154
ActivityLevel
Unknown
0
Rest
1
Inactive
2
Low Intensity
3
Medium Intensity
4
High Intensity
5
HeartRateZone
Zone 0
0
Zone 1
1
Zone 2
2
Zone 3
3
Zone 4
4
Zone 5
5
Other/custom classification
6
SleepLevel
Unknown
0
Awake
1
Sleeping
2
Out of Bed
3
Light
4
Deep
5
REM
6
StrengthSetType
normal
A working set
warmup
Warm-up set
cooldown
Cool-down set
dropset
Weight reduced mid-exercise to continue past failure
failure
Taken to failure
amrap
As many reps as possible
unknown
The source reported something Terra could not resolve — distinct from null, which means it reported nothing
StrengthLoadType
Value
weight_kg means
Counts as added load
external
Load added to the body (plates, dumbbells, the stack)
Yes
bodyweight
No external load; body mass only
No
bodyweight_plus
The extra load only (e.g. a weighted-pull-up belt) — add strength_data.body_weight_kg for total load
Excluded by the rule above
assisted
Load removed to make the movement easier
No
unknown
Unclassified
Treat as no
StrengthSource
user_logged
The user recorded the exercise themselves. Reps and load are what they entered.
device_detected
A wearable inferred the exercise from motion. Treat reps and the exercise itself as estimates, and expect weight_kg to be null more often — the device does not measure load, so it is present only when the user added it afterwards.
unknown
The source reported something Terra could not resolve — distinct from null, which means it reported nothing
Modifier vocabularies
Every axis of modifiers. accommodating_resistance and assistance are also open vocabularies but publish no fixed member list — assistance names what makes the movement easier (machine, band, partner, balance_support), accommodating_resistance names bands or chains added to another implement.
implement
What provides the load
band, barbell, battle_rope, belt, bodyweight, cable, dumbbell, ez_bar, handle_band, kettlebell, landmine, loop_band, machine, machine_assisted, medicine_ball, mini_band, partner, pvc, safety_bar, sled, smith_machine, suspension, trap_bar, weight_plate
surface
What the body is supported on, when it is not the floor
bench, bosu, box, floor, foam_roller, glute_ham_machine, preacher_bench, swiss_ball, treadmill, wall
grip_width
How far apart the hands are
close, wide
grip_orientation
Which way the hands face
bottoms_up, mixed, neutral, overhand, pinch, reverse, underhand
laterality
Whether both limbs work together, alternately, or one at a time
alternating, bilateral, unilateral
stance
Foot arrangement
crossover, curtsy, split, sumo
position
Orientation of the body or bench
bent_over, decline, elevated, flat, forearm, half_kneeling, hanging, incline, inverted, kneeling, lying, pike, prone, quadruped, seated, side_lying, standing, supine
bar_position
Where the implement is carried
behind_back, behind_neck, front_rack, goblet, overhead, zercher
tempo
How the repetition is paced
eccentric, explosive, isometric, kipping, paused, pulse, tempo_slow
rom
How much of the movement is performed, or where it starts
deficit, from_blocks, from_hang, full, partial, to_bench
programme
A programme or population the variant belongs to. Descriptive only — it changes neither the movement nor the load
pregnancy
StrengthMuscle
Used by primary_muscles and secondary_muscles. Members are training groups, not anatomy: a source naming a specific head — pectoralis major sternal, gluteus medius, brachialis, soleus — reports the group it belongs to, so the same exercise groups the same way whichever app recorded it.
abductors, abs, adductors, back, biceps, calves, chest, forearms, glutes, hamstrings, hip_flexor, lat, lower_back, neck, obliques, quadriceps, serratus, shoulders, tibialis, trapezius, triceps, upper_back
Members are added over time, and a new one changes the total of the member it is most closely related to. If you aggregate per muscle, plan for that.
Some members are parts of a broader one and can be summed with it for a coarse view that stays stable: lat + upper_back + back covers the whole back, and obliques + abs the whole midsection.
Others are their own group and should not be folded into a neighbour — serratus is not part of the chest, tibialis is not part of the calves, and hip_flexor is not part of the quadriceps.
StrengthTarget
The body part a stretch or mobility drill acts on. Reported separately from the muscles worked because for a stretch the body part is the exercise. null for ordinary lifts.
abs, adductors, ankle, back, biceps, calves, chest, forearms, glutes, hamstrings, hip, hip_abductor, hip_adductor, hip_flexor, lat, lower_back, neck, obliques, quadriceps, shoulders, spine, thoracic_spine, triceps, upper_back
StrengthMovement
The joint actions an exercise performs, and the axis to match on. movements is an array because one exercise can chain several — a clean and jerk is ["clean", "jerk"] — so test membership, not equality: it belongs in both clean volume and jerk volume.
174 members:
ab_rollout, arm_circle, around_the_world, back_extension, battle_rope_slam, battle_rope_wave, bear_crawl, bicep_curl, bicycle_crunch, bike, bird_dog, body_saw, bound, box_jump, broad_jump, burpee, butt_kick, butt_scoot, calf_raise, carioca, carry, chest_fly, chest_press, chin_up, clamshell, clean, clean_pull, climb, complex, cossack_squat, crunch, dead_bug, deadlift, depth_jump, diaphragmatic_breathing, dip, duck_walk, elliptical, face_pull, farmers_carry, fire_hydrant, flutter_kick, foam_roll, frog_kick, front_raise, glute_bridge, glute_ham_raise, good_morning, halo, hand_walk, handstand_hold, handstand_push_up, handstand_walk, heel_slide, heel_touch, high_knee, high_pull, hike, hip_abduction, hip_adduction, hip_circle, hip_drop, hip_extension, hip_flexion, hip_hinge, hip_thrust, hold, hollow_hold, hop, i_raise, inchworm, jerk, jump, jump_rope, jumping_jack, kick, knee_raise, kneel_to_stand, l_sit, lat_pulldown, lateral_raise, lateral_walk, leg_circle, leg_curl, leg_cycle, leg_extension, leg_press, leg_raise, leg_swing, lunge, march, monster_walk, mountain_climber, muscle_up, neck_extension, neck_flexion, neck_lateral_flexion, oblique_crunch, overhead_press, pallof_press, pike_up, plank, plate_flip, plate_pinch, pull_apart, pull_through, pull_up, pullover, punch, push_press, push_up, rear_delt_fly, reverse_crunch, reverse_hyperextension, romanian_deadlift, rope_climb, row, row_erg, run, russian_twist, scapular_pull_up, scapular_push_up, scapular_retraction, scissor_kick, shoulder_external_rotation, shoulder_internal_rotation, shrug, shuffle, sissy_squat, sit_up, ski_erg, skip, slam, sled_drag, sled_push, snatch, snatch_balance, snatch_pull, squat, stair_climb, star_jump, step_down, step_over, step_up, stiff_legged_deadlift, stomach_vacuum, straight_arm_pulldown, stretch, superman, swim, swimmer, swing, t_raise, throw, thruster, tibialis_raise, tire_flip, toe_tap, toe_walk, tricep_extension, trunk_lateral_flexion, trunk_rotation, turkish_get_up, upright_row, v_sit, v_up, w_raise, walk, walkout, windmill, windshield_wiper, wood_chop, wrist_curl, y_raise
UploadType
Unknown
0
Automatic
1
Manual
2
Update
3
Delete
4
Pending
5
Third party upload
6
SleepUploadType
Unknown
0
Manual
1
Automatic
2
Tentative
3
Indeterminate
4
StrokeType
OTHER
other
FREESTYLE
freestyle
BACKSTROKE
backstroke
BREASTSTROKE
breaststroke
BUTTERFLY
butterfly
GlucoseFlag
Normal
0
High
1
Low
2
NutritionUnits
Unknown
0
Gram
1
Teaspoon
2
Tablespoon
3
Cup
4
Medium
5
Large
6
Small
7
Milliliter
8
Ounce
9
Count
10
Scoop
11
Fluid Ounce
12
RecoveryLevel
Unknown
0
Very Poor
1
Poor
2
Compromised
3
Ok
4
Good
5
Very Good
6
TrendArrow
UNKNOWN
0
FALLING_QUICKLY
1
FALLING
2
FLAT
3
RISING
4
RISING_QUICKLY
5
Timezone Localization
UTC
0
LOCAL
1
MenstruationFlow
UNKNOWN
0
NONE
1
LIGHT
2
MEDIUM
3
HEAVY
4
HARD
5
MealType
UNKNOWN
0
BREAKFAST
1
MORNING_SNACK
2
LUNCH
3
AFTERNOON_SNACK
4
DINNER
5
SNACK
6
StressLevel
NOT_ENOUGH_DATA
0
REST
1
LOW
2
MEDIUM
3
HIGH
4
HeartRateContext
NOT_SET
0
ACTIVE
1
NOT_ACTIVE
2
MenstruationInterval
UNKNOWN
0
PERIOD
1
FOLLICULAR
2
FERTILE_WINDOW
3
OVULATION
4
LUTEAL
5
PMS
6
FIRST_TRIMESTER
7
SECOND_TRIMESTER
8
THIRD_TRIMESTER
9
PlannedWorkout
The Workout Types follow the same numbering as the Activity Types that can be found in https://docs.tryterra.co/reference/enums#activitytype
PlannedWorkoutStep
REST
0
WARMUP
1
COOLDOWN
2
RECOVERY
3
INTERVAL
4
ACTIVE
5
PlannedWorkoutRepeatStep
PlannedWorkoutStepTarget
SPEED
{ "target_type": 0, "speed_meters_per_second": Number, "speed_meters_per_second_low": Number, "speed_meters_per_second_high": Number }
HEART_RATE
{ "target_type": 1, "hr_bpm_high": Number, "hr_bpm_low": Number }
OPEN
{ "target_type": 2 }
CADENCE
{ "target_type": 3, "cadence": Number, "cadence_high": Number, "cadence_low" : Number }
POWER
{ "target_type": 4, "power_watt_high": Number, "power_watt_low": Number, "power_watt": Number }
SWIM_STROKE
{ "target_type": 8, "swim_strokes": Number }
PACE
{ "target_type": 11, "speed_meters_per_second": Number, "speed_meters_per_second_low": Number, "speed_meters_per_second_high": Number }
HEART_RATE_THRESHOLD_PERCENTAGE
{ "target_type": 12, "hr_percentage": Number, "hr_percentage_low": Number, "hr_percentage_high": Number }
HEART_RATE_MAX_PERCENTAGE
{ "target_type": 13, "hr_percentage": Number, "hr_percentage_low": Number, "hr_percentage_high": Number }
SPEED_PERCENTAGE
{ "target_type": 14, "speed_percentage": Number, "speed_percentage_low": Number, "speed_percentage_high": Number }
POWER_PERCENTAGE
{ "target_type": 15, "power_percentage": Number, "power_percentage_low": Number, "power_percentage_high": Number }
REPETITION
{ "target_type": 16, "repetitions": Number }
PlannedWorkoutStepDuration
TIME
{ "duration_type": 0, "seconds": Number }
DISTANCE_METERS
{ "duration_type": 1, "distance_meters": Number }
HR_LESS_THAN
{ "duration_type": 2, "hr_below_bpm": Number }
HR_GREATER_THAN
{ "duration_type": 3, "hr_above_bpm": Number }
CALORIES
{ "duration_type": 4, "calories": 2.0 }
OPEN
{ "duration_type": 5 }
POWER_LESS_THAN
{ "duration_type": 6, "power_below_watts": Number }
POWER_GREATER_THAN
{ "duration_type": 7, "power_above_watts": Number }
REPS
{ "duration_type": 9, "reps": Number }
FIXED_REST
{ "duration_type": 10, "rest_seconds": Number }
STEPS
{ "duration_type": 12, "steps": Number }
Enums
BACKSTROKE
0
BREASTSTROKE
1
DRILL
2
BUTTERFLY
3
FREESTYLE
4
MIXED
5
IM
6
NONE
0
SWIM_FINS
1
SWIM_KICKBOARD
2
SWIM_PADDLES
3
SWIM_PULL_BUOY
4
SWIM_SNORKEL
5
UNKNOWN
0
BENCH_PRESS
1
CALF_RAISE
2
CARDIO
3
CARRY
4
CHOP
5
CORE
6
CRUNCH
7
CURL
8
DEADLIFT
9
FLYE
10
HIP_RAISE
11
HIP_STABILITY
12
HIP_SWING
13
HYPEREXTENSION
14
LATERAL_RAISE
15
LEG_CURL
16
LEG_RAISE
17
LUNGE
18
OLYMPIC_LIFT
19
PLANK
20
PLYO
21
PULL_UP
22
PUSH_UP
23
ROW
24
SHOULDER_PRESS
25
SHOULDER_STABILITY
26
SHRUG
27
SIT_UP
28
SQUAT
29
TOTAL_BODY
30
TRICEPS_EXTENSION
31
WARM_UP
32
RUN
33
BIKE
34
CARDIO_SENSORS
35
Last updated
Was this helpful?