Skip to content

Mapping — Hevy

Source: Hevy CSV export (one row per set). Pillar: B (strength). Mapper: mapHevymapHevy(csv) → records[], one Session per workout.

Structural correspondence

Hevy CSVOpenBody
a workout (rows sharing title + start_time)Session (disciplines: ["strength"], nametitle, notesdescription)
consecutive rows for one exercise_titleExercise (exerciseRef: { opaque: <title> })
one set rowWorkUnit (scoring from which columns are present)
set_type (normal|warmup|drop|failure)WorkUnit.setRole (working|warmup|drop|failure)
weight_kgperformance.load (unit: "kg")
reps / distance_km / duration_secondsperformance.reps / .distance / .time
rpeperformance.effortLoad ({ kind: "internal", method: "RPE", value })
superset_id (non-empty)a Block with grouping: "superset"

Input (one set)

"title","start_time","end_time",...,"exercise_title","superset_id",...,"set_type","weight_kg","reps",...,"rpe"
"Morning workout","22 Dec 2025, 08:00","22 Dec 2025, 08:37",...,"Pull Up (Assisted)",,...,"normal",21,10,,0,8.5

Output (OpenBody wire record)

{
"id": "hevy-sess-1",
"recordType": "Session",
"subject": "subj-001",
"name": "Morning workout",
"disciplines": ["strength"],
"startTime": "2025-12-22T08:00:00Z",
"endTime": "2025-12-22T08:37:00Z",
"exercises": [
{
"id": "hevy-sess-1-ex0",
"recordType": "Exercise",
"exerciseRef": { "opaque": "Pull Up (Assisted)" },
"workUnits": [
{
"id": "hevy-sess-1-ex0-set0",
"recordType": "WorkUnit",
"scoring": "reps",
"setRole": "working",
"performance": {
"reps": 10,
"load": { "value": 21, "unit": "kg", "basis": "assist" },
"effortLoad": [{ "kind": "internal", "method": "RPE", "value": 8.5 }]
}
}
]
}
]
}

Notes & edge cases

  • Workout title maps to the first-class name (added in v0.3); the first Hevy mapper silently dropped it — a real losslessness bug that dogfooding surfaced.
  • Supersets force all-blocks. A Session carries at most one of blocks|exercises|workUnits (§5.3). If any row has a superset_id, the mapper emits everything under blocks[], wrapping standalone exercises in singleton Blocks and grouping superset mates in a Block with grouping: "superset".
  • Scoring is chosen per set: reps if present, else distance, else time — so plank and cardio rows map cleanly alongside strength sets.
  • Exercise identity uses the opaque floor — lossless now, registry-resolvable later via the matching ladder.