History Export Spec v1.1

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.

Overview

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:

  • Dual-unit weights — All weights include both kg and lb values for universal compatibility
  • Pre-computed analytics — Session strain scores, volume, and training zones are pre-calculated
  • Hierarchical muscle groups — Detailed muscle targeting with primary/secondary breakdown
  • ISO 8601 timestamps — All dates and times in UTC for unambiguous time handling

Versioning & Compatibility

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.

Root Object

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.

Volume Analytics Object v1.1

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" }
    }
  }
}

windows

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.

trends

Daily effective volume values and rolling averages for each window. Rolling window sizes by period:

records

Two record scopes are included:

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.

Session Object

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.

Analytics Object

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"

Strain Zones

Exercise Instance

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.

Set Object

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.)

Weight Values

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.

Timer Logs

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.

Capabilities Reference

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

Common Combinations

Integration Guidance

For Coaches

When analysing exported workout history, focus on these key metrics:

  1. Volume Trends — Track analytics.totalVolume over time to monitor progressive overload
  2. Strain Distribution — Use analytics.strainZone to ensure balanced recovery/productive/excessive ratio
  3. Failure Set Frequency — High failureSetCount may indicate need for deload
  4. Session DurationdurationMinutes helps identify training efficiency

Volume calculation notes:

  • Warm-up sets (isWarmup: true) are excluded from totalVolume
  • Failure sets (isFailure: true) receive a 1.5x multiplier
  • Bodyweight exercises use user's body weight when bodyweightVolume capability is present
  • doublesVolume: true exercises have their volume doubled (unilateral movements)

For AI/LLM Systems

Tips for parsing Intrvl history exports:

  1. Date Handling — All timestamps are ISO 8601 UTC. Convert to user's timezone if needed.
  2. Null Handling — Optional fields are explicitly null when not present, not missing from the object.
  3. Weight Values — Use weight.kg as the authoritative value; weight.lb is calculated.
  4. Session Filtering — Check isComplete to filter out empty/abandoned sessions.
  5. Exercise Grouping — Use category or muscleGroups.primary keys to group exercises by body part.

For Data Backup

Export Constraints

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

Filename Convention

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)

Complete Example

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"
        }
      ]
    }
  ]
}

Need Help?

Questions about the History Export format? Get in touch: