The Program Import Format lets you generate a structured workout program with an AI tool and import it directly into the Temper mobile app.
workouts and cycle. For a periodized program, use phases instead — never both.cycle array (top-level or per-phase) is required in its context. Rest days are objects — { "type": "rest" } — not the string "Rest".exerciseRef — the Temper exercise catalog ID.trackingType to choose the target field: reps for "reps" exercises, durationSeconds for "duration" exercises.trackingType in program JSON; it comes from the exercise catalog.reps.min must be less than or equal to reps.max.setTypes is provided, its length must equal sets.cycle must match a workout name in the same scope.| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Program display name |
context |
string |
Yes | Context about the user or goals |
description |
string |
Yes | Short description shown to the user |
workouts |
array |
When no phases |
List of workouts (minimum 1) |
cycle |
array |
When no phases |
Ordered cycle slots (minimum 1) |
phases |
array |
When no workouts/cycle |
Ordered list of program phases (minimum 2) — use for periodized programs |
trainingGuidelines |
object |
No | Auto-progression, missed-target, and deload policies |
Each entry in cycle (top-level or per-phase) is one of:
name within the same scope{ "type": "rest" }Used when the program is periodized (e.g. hypertrophy block → strength block). Phases run in order; each phase repeats its cycle cycleRepetitions times before advancing.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Display name (e.g. "Hypertrophy Block") |
cycleRepetitions |
integer ≥ 1 |
Yes | How many times to complete this phase’s cycle before advancing to the next |
workouts |
array |
Yes | Phase-specific workouts — same structure as top-level workouts |
cycle |
array |
Yes | Phase-specific cycle — strings must match workout names within this phase |
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Display name — must be unique |
exercises |
array |
Yes | List of exercises (minimum 1) |
focus |
string |
No | Workout focus category — see valid values below |
supersets |
string[][] |
No | Superset groups — see below |
Valid focus values: "push", "pull", "legs", "upper", "lower", "full_body", "core"
| Field | Type | Required | Description |
|---|---|---|---|
exerciseRef |
string |
Yes | Temper exercise catalog ID |
sets |
integer ≥ 1 |
Yes | Total number of sets |
reps |
{ min, max } |
For reps exercises | Target rep range |
durationSeconds |
integer ≥ 1 |
For duration exercises | Target duration in seconds |
rest |
{ workSeconds, warmupSeconds? } |
Yes | Rest configuration |
setTypes |
string[] |
No | Per-set type labels — length must equal sets |
notes |
string |
No | Notes shown to the user |
Use exactly one target field per exercise. If the catalog row has trackingType: "reps", include reps and omit durationSeconds. If the catalog row has trackingType: "duration", include durationSeconds and omit reps.
rest.workSeconds — rest after work sets, in seconds (minimum 1).
rest.warmupSeconds — rest after warmup sets, in seconds (minimum 0, defaults to 0).
| Value | Meaning |
|---|---|
work |
Standard working set (default when setTypes is omitted) |
warmup |
Warm-up set |
drop |
Drop set — reduce weight immediately after the previous set |
failure |
Go to failure |
supersets is an optional array of groups. Each group is an array of exercise names (minimum 2) that will be performed as a superset. The exercises in a group must be adjacent in the workout’s exercises list and each exercise can only belong to one group.
trainingGuidelinesOptional object controlling automatic progression. All three policies are required when the field is present.
progressionPolicy — how weight progresses between sessions:
{ "type": "manual" } — user adjusts weight manually{ "type": "linear", "upperBodyIncrement": 2.5, "lowerBodyIncrement": 5, "requireAllWorkSetsCompleted": true } — add weight each session{ "type": "double_progression", "defaultIncrement": 2.5 } — progress reps before adding weightmissedTargetPolicy — what happens when the user misses the rep target:
{ "type": "manual" } — user decides{ "type": "repeat_then_reduce", "missesBeforeReduction": 2, "reductionPercent": 10 } — deload after N missesdeloadPolicy — when and how to deload:
{ "type": "manual" } — user initiates deload{ "type": "every_n_weeks", "everyNWeeks": 4, "loadPercent": 70 } — scheduled deloadAvoid these — they are not part of the v1 import format:
exerciseRef values reference the Temper exercise catalog. The catalog is synced separately — use the IDs and trackingType values provided by the catalog for production programs.
{
"name": "Upper/Lower Split",
"context": "Intermediate lifter, training 4 days per week, focused on hypertrophy.",
"description": "4-day upper/lower program alternating horizontal and vertical emphasis.",
"cycle": [
"Upper A",
"Lower A",
{ "type": "rest" },
"Upper B",
"Lower B",
{ "type": "rest" },
{ "type": "rest" }
],
"workouts": [
{
"name": "Upper A",
"focus": "upper",
"exercises": [
{
"exerciseRef": "ex_M8-whQhCC2l-pDKA",
"sets": 4,
"reps": { "min": 6, "max": 10 },
"rest": { "workSeconds": 120, "warmupSeconds": 60 },
"setTypes": ["warmup", "work", "work", "work"]
},
{
"exerciseRef": "ex_jRszZ9t0mrLArO5j",
"sets": 4,
"reps": { "min": 6, "max": 10 },
"rest": { "workSeconds": 120 }
},
{
"exerciseRef": "ex_rOkrYlUeujBx7bJS",
"sets": 3,
"durationSeconds": 45,
"rest": { "workSeconds": 60 },
"notes": "Duration target from a catalog exercise with trackingType \"duration\"."
}
]
},
{
"name": "Lower A",
"focus": "legs",
"exercises": [
{
"exerciseRef": "ex_68cMQ5G3jPG1CpRT",
"sets": 4,
"reps": { "min": 5, "max": 8 },
"rest": { "workSeconds": 150, "warmupSeconds": 90 },
"setTypes": ["warmup", "work", "work", "work"]
},
{
"exerciseRef": "ex_mNDQcSGhYO_I-b6Y",
"sets": 3,
"reps": { "min": 10, "max": 12 },
"rest": { "workSeconds": 120 }
}
]
},
{
"name": "Upper B",
"focus": "upper",
"exercises": [
{
"exerciseRef": "ex_6GdtGj4pdOKW4sam",
"sets": 4,
"reps": { "min": 6, "max": 10 },
"rest": { "workSeconds": 120, "warmupSeconds": 60 },
"setTypes": ["warmup", "work", "work", "work"]
},
{
"exerciseRef": "ex_S7rjIBFoRGnHDuin",
"sets": 4,
"reps": { "min": 6, "max": 10 },
"rest": { "workSeconds": 120 }
}
]
},
{
"name": "Lower B",
"focus": "legs",
"exercises": [
{
"exerciseRef": "ex_Kn9VQU_nzgSIK99W",
"sets": 4,
"reps": { "min": 4, "max": 6 },
"rest": { "workSeconds": 180, "warmupSeconds": 90 },
"setTypes": ["warmup", "work", "work", "work"]
},
{
"exerciseRef": "ex_DioMiKJU4E8pNnb8",
"sets": 3,
"reps": { "min": 8, "max": 12 },
"rest": { "workSeconds": 90 }
}
]
}
]
}
See the examples directory for complete programs.
Use phases instead of top-level workouts and cycle for periodized programs. Each phase has its own workouts, cycle, and repetition count.
{
"name": "Hypertrophy to Strength",
"context": "Intermediate lifter, training 4 days per week.",
"description": "Two-phase program: 4 weeks of hypertrophy followed by 3 weeks of strength.",
"phases": [
{
"name": "Hypertrophy",
"cycleRepetitions": 4,
"workouts": [
{
"name": "Upper",
"focus": "upper",
"exercises": [
{
"exerciseRef": "ex_M8-whQhCC2l-pDKA",
"sets": 4,
"reps": { "min": 8, "max": 12 },
"rest": { "workSeconds": 90 }
}
]
},
{
"name": "Lower",
"focus": "legs",
"exercises": [
{
"exerciseRef": "ex_68cMQ5G3jPG1CpRT",
"sets": 4,
"reps": { "min": 8, "max": 12 },
"rest": { "workSeconds": 120 }
}
]
}
],
"cycle": ["Upper", { "type": "rest" }, "Lower", { "type": "rest" }]
},
{
"name": "Strength",
"cycleRepetitions": 3,
"workouts": [
{
"name": "Upper",
"focus": "upper",
"exercises": [
{
"exerciseRef": "ex_M8-whQhCC2l-pDKA",
"sets": 5,
"reps": { "min": 3, "max": 5 },
"rest": { "workSeconds": 180 }
}
]
},
{
"name": "Lower",
"focus": "legs",
"exercises": [
{
"exerciseRef": "ex_68cMQ5G3jPG1CpRT",
"sets": 5,
"reps": { "min": 3, "max": 5 },
"rest": { "workSeconds": 180 }
}
]
}
],
"cycle": ["Upper", { "type": "rest" }, "Lower", { "type": "rest" }]
}
]
}