Export your training history as structured JSON. Share workout data with coaches for programming adjustments, feed it to AI tools for analysis, or import it into the Intrvl Analytics dashboard for visual performance review.
This spec is for exported training history data (sessions, exercises, sets, analytics). For structured workout programs, see the Program Collection Spec. For standalone exercise import/export, see the Exercise Spec.
Current version: 1.1 (App 2.7.1+). Adds volumeAnalytics for coach workflows. Fully backward compatible with v1.0.
The Intrvl history export format provides a complete, structured representation of workout sessions within a selected date range. The JSON format is designed for:
Key features:
| Version | App Version | Changes |
|---|---|---|
"1.1" |
2.7.1+ | Adds optional volumeAnalytics top-level object for coach workflows. |
"1.0" |
2.7.0+ | Initial release. Sessions, exercises, sets, analytics. |
Backward compatibility: v1.1 keeps all v1.0 fields and semantics. v1.0 consumers that ignore unknown fields can safely parse v1.1 exports. Only the optional volumeAnalytics top-level field is new; session and set structures are unchanged.
The top-level export object contains metadata and an array of sessions. v1.1 adds the optional volumeAnalytics field.
{
"version": "1.1",
"exportDate": "2026-01-30T12:00:00.000Z",
"appVersion": "2.7.1",
"dateRange": {
"from": "2026-01-01",
"to": "2026-01-30"
},
"unitPreference": "kg",
"volumeAnalytics": { "...": "..." },
"sessions": [...]
}
| Field | Type | Required | Description |
|---|---|---|---|
version |
String | Yes | Schema version. "1.1" or "1.0" |
exportDate |
String | Yes | ISO 8601 UTC timestamp when the export was created |
appVersion |
String | Yes | App version that created the export (e.g., "2.7.1") |
dateRange.from |
String | Yes | Start date in YYYY-MM-DD format |
dateRange.to |
String | Yes | End date in YYYY-MM-DD format (inclusive) |
unitPreference |
String | Yes | User's preferred unit system: "kg" or "lb" |
volumeAnalytics |
Object | No | v1.1+ Coach-facing effective volume analytics for the exported date range. null or absent in v1.0 exports. |
sessions |
Array | Yes | Array of Session objects (may be empty) |
Important: Unlike the Program Collection Spec, the version field here is a string ("1.1"), not a number. This matches the history export schema convention.
volumeAnalytics is anchored to dateRange.to and uses effective volume (kg) as the metric basis. Designed for coach review workflows. All dates use YYYY-MM-DD format.
{
"metric": "effectiveVolumeKg",
"anchorDate": "2026-01-30",
"windows": [
{ "windowDays": 7, "current": 12000, "previous": 10000, "deltaPercent": 20, "status": "comparable" },
{ "windowDays": 14, "current": 23000, "previous": 21000, "deltaPercent": 9.5, "status": "comparable" },
{ "windowDays": 30, "current": 42000, "previous": 0, "deltaPercent": null, "status": "noPreviousData" },
{ "windowDays": 60, "current": 79000, "previous": 72000, "deltaPercent": 9.7, "status": "comparable" },
{ "windowDays": 90, "current": 0, "previous": 18000, "deltaPercent": null, "status": "noCurrentData" }
],
"trends": [
{
"windowDays": 7,
"rollingWindowDays": 3,
"points": [
{ "date": "2026-01-24", "effectiveVolume": 1200, "rollingAverage": 1200 },
{ "date": "2026-01-25", "effectiveVolume": 1800, "rollingAverage": 1500 }
]
}
],
"records": {
"lifetime": {
"highestWeeklyVolume": { "value": 33000, "date": "2026-01-21" },
"highestDailyVolume": { "value": 6200, "date": "2026-01-19" },
"mostSetsInDay": { "value": 32, "date": "2026-01-18" }
},
"exportRange": {
"highestWeeklyVolume": { "value": 21000, "date": "2026-01-28" },
"highestDailyVolume": { "value": 5100, "date": "2026-01-27" },
"mostSetsInDay": { "value": 24, "date": "2026-01-26" }
}
}
}
Each window compares current and previous trailing periods ending at anchorDate. Windows: 7, 14, 30, 60, 90 days.
| Field | Type | Required | Description |
|---|---|---|---|
windowDays |
Number | Yes | Window size: 7, 14, 30, 60, or 90. |
current |
Number | Yes | Total effective volume (kg) for the current window period. |
previous |
Number | Yes | Total effective volume (kg) for the previous window period of equal length. |
deltaPercent |
Number | No | (current - previous) / previous * 100, or null when not comparable. |
status |
String | Yes | One of: comparable, noCurrentData, insufficientHistory, noPreviousData. |
Daily effective volume values and rolling averages for each window. Rolling window sizes by period:
rollingWindowDays: 3rollingWindowDays: 5rollingWindowDays: 7rollingWindowDays: 10rollingWindowDays: 14Two record scopes are included:
lifetime — All sessions up to anchorDateexportRange — Sessions within dateRange only| Record | Description |
|---|---|
highestWeeklyVolume |
Maximum rolling 7-day effective volume sum. date is the last day of that 7-day window. |
highestDailyVolume |
Maximum single-day effective volume. |
mostSetsInDay |
Maximum total set count in one day, including warm-up sets. |
Volume calculation notes: Effective volume excludes warm-up sets and follows existing workload formulas. All dates in volumeAnalytics use YYYY-MM-DD. Session-level and set-level fields from v1.0 are unchanged.
Each session represents a single workout day with exercises, sets, and analytics.
| Field | Type | Required | Description |
|---|---|---|---|
id |
String | Yes | UUID uniquely identifying the session |
date |
String | Yes | ISO 8601 UTC timestamp of the session date |
startTime |
String | No | ISO 8601 UTC timestamp of the first logged set. null if no sets. |
endTime |
String | No | ISO 8601 UTC timestamp of the last logged set. null if no sets. |
durationMinutes |
Number | No | Session duration in minutes (first to last set). null if fewer than 2 sets. |
notes |
String | No | User-entered session notes. null if not provided. |
isComplete |
Boolean | Yes | true if session has at least one set logged. |
analytics |
Object | No | Session analytics. null if no sets logged. |
exercises |
Array | Yes | Array of Exercise Instance objects (ordered by first set timestamp). |
timerLogs |
Array | No | Array of Timer Log objects. null if no timer activity. |
Completion heuristic: A session is isComplete: true if it contains at least one logged set. Sessions without sets (user opened but logged nothing) have isComplete: false.
Pre-computed analytics for the session. Only present when the session has logged sets.
| Field | Type | Description |
|---|---|---|
strainScore |
Number | Computed strain score for the session (0-100+ scale). Higher values indicate more demanding sessions. |
totalVolume |
Number | Total effective volume in kilograms. Sum of (weight x reps) for working sets, with adjustments for bodyweight and failure sets. |
hardSetCount |
Number | Count of non-warmup sets (working sets that contribute to volume). |
failureSetCount |
Number | Count of sets marked as taken to failure. |
trainingLevel |
String | User's configured training level: "beginner", "intermediate", "advanced" |
strainZone |
String | Session intensity classification: "recovery", "productive", "excessive" |
Each exercise instance represents an exercise performed within a session, including all metadata and logged sets.
| Field | Type | Required | Description |
|---|---|---|---|
name |
String | Yes | Exercise name as displayed in the app. |
category |
String | No | Primary muscle category (e.g., "Chest", "Back"). null if uncategorised. |
capabilities |
Array | Yes | Capability strings defining what metrics this exercise tracks. |
muscleGroups |
Object | No | Hierarchical muscle group mapping with primary and secondary breakdown. null if not configured. |
equipment |
Array | No | Equipment names required. null if bodyweight-only. |
doublesVolume |
Boolean | Yes | true for unilateral exercises where volume is doubled. |
sets |
Array | Yes | Array of Set objects in chronological order. |
Individual set data with all logged metrics.
| Field | Type | Required | Description |
|---|---|---|---|
setNumber |
Number | Yes | 1-indexed position within the exercise (first set = 1). |
timestamp |
String | Yes | ISO 8601 UTC timestamp when the set was logged. |
weight |
Object | No | Weight value with dual units. null for bodyweight-only sets. |
reps |
Number | No | Repetition count. null for timed-only sets. |
duration |
Number | No | Duration in seconds. null for rep-based sets. |
distance |
Number | No | Distance in metres. null if not a distance-based exercise. |
notes |
String | No | Set-specific notes. null if none. |
isWarmup |
Boolean | Yes | true if marked as warm-up. Excluded from effective volume. |
isFailure |
Boolean | Yes | true if marked as taken to failure. 1.5x volume multiplier. |
isPR |
Boolean | Yes | true if personal record. (Currently always false; future enhancement.) |
restSeconds |
Number | No | Rest period before this set in seconds. (Currently always null; future enhancement.) |
All weight values include both metric and imperial units for universal compatibility.
{
"kg": 100,
"lb": 220.46
}
| Field | Type | Description |
|---|---|---|
kg |
Number | Weight in kilograms. This is the source of truth. |
lb |
Number | Weight in pounds (calculated: kg * 2.20462). |
Important: The kg value is the source of truth stored in the app. The lb value is calculated at export time. For maximum precision when importing, use the kg value.
Records of timer usage during the session (rest timers, interval timers).
| Field | Type | Required | Description |
|---|---|---|---|
timestamp |
String | Yes | ISO 8601 UTC timestamp when the timer completed. |
duration |
Number | Yes | Timer duration in seconds. |
timerType |
String | No | Timer type identifier (e.g., "rest"). null if not specified. |
The capabilities array defines what metrics an exercise tracks. These are the same capability values used in the Exercise Spec and Program Collection Spec.
| Value | Description |
|---|---|
weight |
Exercise uses external weight (barbell, dumbbell, machine) |
reps |
Exercise tracks repetition count |
duration |
Exercise tracks time (for timed holds, intervals) |
distance |
Exercise tracks distance (for carries, cardio) |
bodyweightVolume |
Volume calculation includes user's body weight |
["weight", "reps"] — Traditional weighted exercises (Bench Press, Squat)["reps", "bodyweightVolume"] — Bodyweight exercises with volume tracking (Push-ups, Pull-ups)["weight", "reps", "bodyweightVolume"] — Weighted bodyweight (Weighted Dips, Weighted Pull-ups)["weight", "distance"] — Loaded carries (Farmer's Walk)["duration"] — Timed holds (Plank)When analysing exported workout history, focus on these key metrics:
analytics.totalVolume over time to monitor progressive overloadanalytics.strainZone to ensure balanced recovery/productive/excessive ratiofailureSetCount may indicate need for deloaddurationMinutes helps identify training efficiencyVolume calculation notes:
isWarmup: true) are excluded from totalVolumeisFailure: true) receive a 1.5x multiplierbodyweightVolume capability is presentdoublesVolume: true exercises have their volume doubled (unilateral movements)Tips for parsing Intrvl history exports:
null when not present, not missing from the object.weight.kg as the authoritative value; weight.lb is calculated.isComplete to filter out empty/abandoned sessions.category or muscleGroups.primary keys to group exercises by body part.| Constraint | Value | Description |
|---|---|---|
| Maximum Date Range | 90 days | Single export cannot exceed 90 days to manage file size |
| File Format | JSON | Only JSON format is supported |
| Encoding | UTF-8 | All text is UTF-8 encoded |
| Timestamps | UTC | All timestamps are in UTC timezone |
workout-history-{from-date}-to-{to-date}.json
Examples: workout-history-2026-01-01-to-2026-01-30.json, workout-history-2026-01-15-to-2026-01-15.json (single day)
A full v1.1 export showing the volumeAnalytics object alongside session data:
{
"version": "1.1",
"exportDate": "2026-01-30T14:00:00.000Z",
"appVersion": "2.7.1",
"dateRange": {
"from": "2026-01-28",
"to": "2026-01-30"
},
"unitPreference": "kg",
"volumeAnalytics": {
"metric": "effectiveVolumeKg",
"anchorDate": "2026-01-30",
"windows": [
{ "windowDays": 7, "current": 12000, "previous": 10000, "deltaPercent": 20, "status": "comparable" },
{ "windowDays": 14, "current": 23000, "previous": 21000, "deltaPercent": 9.5, "status": "comparable" }
],
"trends": [
{
"windowDays": 7,
"rollingWindowDays": 3,
"points": [
{ "date": "2026-01-28", "effectiveVolume": 9850, "rollingAverage": 9850 }
]
}
],
"records": {
"lifetime": {
"highestWeeklyVolume": { "value": 33000, "date": "2026-01-21" },
"highestDailyVolume": { "value": 9850, "date": "2026-01-28" },
"mostSetsInDay": { "value": 14, "date": "2026-01-28" }
},
"exportRange": {
"highestWeeklyVolume": { "value": 12000, "date": "2026-01-30" },
"highestDailyVolume": { "value": 9850, "date": "2026-01-28" },
"mostSetsInDay": { "value": 14, "date": "2026-01-28" }
}
}
},
"sessions": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"date": "2026-01-28T00:00:00.000Z",
"startTime": "2026-01-28T09:05:00.000Z",
"endTime": "2026-01-28T10:15:00.000Z",
"durationMinutes": 70.0,
"notes": "Push day - felt strong",
"isComplete": true,
"analytics": {
"strainScore": 42.3,
"totalVolume": 9850,
"hardSetCount": 14,
"failureSetCount": 2,
"trainingLevel": "intermediate",
"strainZone": "productive"
},
"exercises": [
{
"name": "Bench Press",
"category": "Chest",
"capabilities": ["weight", "reps"],
"muscleGroups": {
"primary": { "Chest": ["Middle Chest"] },
"secondary": { "Arms": ["Triceps"], "Shoulders": ["Front Delts"] }
},
"equipment": ["Barbell", "Bench"],
"doublesVolume": false,
"sets": [
{
"setNumber": 1,
"timestamp": "2026-01-28T09:05:00.000Z",
"weight": { "kg": 60, "lb": 132.28 },
"reps": 10,
"duration": null,
"distance": null,
"notes": null,
"isWarmup": true,
"isFailure": false,
"isPR": false,
"restSeconds": null
},
{
"setNumber": 2,
"timestamp": "2026-01-28T09:10:00.000Z",
"weight": { "kg": 80, "lb": 176.37 },
"reps": 8,
"duration": null,
"distance": null,
"notes": null,
"isWarmup": false,
"isFailure": false,
"isPR": false,
"restSeconds": null
},
{
"setNumber": 3,
"timestamp": "2026-01-28T09:20:00.000Z",
"weight": { "kg": 80, "lb": 176.37 },
"reps": 6,
"duration": null,
"distance": null,
"notes": null,
"isWarmup": false,
"isFailure": true,
"isPR": false,
"restSeconds": null
}
]
},
{
"name": "Push-ups",
"category": "Chest",
"capabilities": ["reps", "bodyweightVolume"],
"muscleGroups": {
"primary": { "Chest": ["Middle Chest"] },
"secondary": { "Arms": ["Triceps"] }
},
"equipment": null,
"doublesVolume": false,
"sets": [
{
"setNumber": 1,
"timestamp": "2026-01-28T09:50:00.000Z",
"weight": null,
"reps": 20,
"duration": null,
"distance": null,
"notes": null,
"isWarmup": false,
"isFailure": false,
"isPR": false,
"restSeconds": null
}
]
}
],
"timerLogs": [
{
"timestamp": "2026-01-28T09:08:00.000Z",
"duration": 120,
"timerType": "rest"
}
]
}
]
}
Questions about the History Export format? Get in touch: