JSON Reference
Technical documentation of the CustomTemplate format for IronPen. For AI generation, advanced users and developers.
Introduction
A custom template in IronPen is a JSON document describing a complete training program — exercises, sets, weights, schedule and progression. The app generates specific workouts from it based on the user's 1RM maxes.
This document describes every field, validation rules and includes complete examples. You can create the JSON manually, have it generated by AI, or export it from the in-app editor.
.json file and use 📁 Import from File.Quick Start
Minimal working template — 1 day, 1 exercise, 1 set:
{
"version": 1,
"meta": {
"id": "muj-prvni-program",
"nameCs": "Můj první program",
"nameEn": "My First Program",
"icon": "💪",
"tags": ["beginner", "strength"]
},
"config": {
"daysPerWeek": [3],
"weeksPerCycle": 4,
"maxCycles": 4,
"trainingMaxPercent": 0.9,
"requiredInputs": [{
"key": "bench1RM",
"labelCs": "Bench Press 1RM",
"labelEn": "Bench Press 1RM",
"type": "WEIGHT_INPUT",
"defaultValue": 60.0,
"linkedExerciseId": "bench-press",
"suffix": "kg"
}]
},
"schedule": {
"type": "WEEKLY_FIXED",
"fixedDays": [{
"dayIndex": 0,
"labelCs": "Trénink",
"labelEn": "Workout",
"exercises": [{
"exerciseId": "bench-press",
"exerciseName": "Bench Press",
"orderIndex": 0,
"exerciseType": "MAIN",
"sets": [{
"reps": "5",
"setType": "MAIN",
"weightSource": {
"type": "PERCENT_TM",
"value": 0.85,
"linkedExerciseId": "bench-press"
},
"copies": 5
}]
}]
}]
},
"progressionRules": []
}
AI Prompt
Copy this entire page (or its URL) into the AI context and add your request. Example prompt:
Vytvoř IronPen custom šablonu (JSON) pro tento program:
- 4 dny/týden (Upper/Lower split)
- 6 týdnů v cyklu
- Hlavní cviky: Squat, Bench, Deadlift, OHP
- Procenta z Training Max (90% z 1RM)
- Wendler-style progrese: +2.5 kg upper, +5 kg lower per cyklus
- Warmup série + 3 pracovní série + BBB 5×10
Použij formát popsaný v JSON Reference dokumentu.
Výsledek musí být validní JSON importovatelný do IronPen.
Root Object — CustomTemplate
| Field | Type | Description |
|---|---|---|
| version | Int | Schema version. Always 1. |
| meta | Object | Template metadata (name, icon, tags). |
| config | Object | Generation config (days/week, cycles, TM%). |
| schedule | Object | Schedule structure (1 of 5 types). |
| progressionRules | Array | Automatic progression rules. Empty array = no progression. |
meta — TemplateMeta
| Field | Type | Description |
|---|---|---|
| id | String | Unique ID. Format: username_slug or any. No spaces or special characters. |
| nameCs | String | Name in Czech. At least one of nameCs/nameEn must be non-empty. |
| nameEn | String | Name in English. If empty, nameCs is used. |
| descriptionCs | String | Description in Czech. |
| descriptionEn | String | Description in English. |
| icon | String | Emoji icon. Default: 💪 |
| tags | Array<String> | Categories: beginner, intermediate, advanced, strength, hypertrophy, endurance |
| createdAt | Long | Creation timestamp (ms). Auto-generated on import. |
| updatedAt | Long | Last update timestamp (ms). |
config — TemplateGenerationConfig
| Field | Type | Description |
|---|---|---|
| daysPerWeek | Array<Int> | Supported day variants. E.g. [3, 4] = template works for 3 or 4 days/week. |
| weeksPerCycle | Int | Number of weeks per cycle. Default: 4. Range: 1–52. |
| maxCycles | Int | Maximum number of cycles. Default: 6. |
| trainingMaxPercent | Float | TM = 1RM × this value. Default: 0.9 (90%). Range: 0.5–1.0. |
| weightIncrement | Float | Weight rounding. Default: 2.5 kg. |
| supportsMultipleCycles | Bool | Allow multiple cycles. Default: true. |
| requiredInputs | Array | Inputs required from the user during generation. See details. |
| deloadConfig | Object | Deload week configuration. See details. |
| weeklyProgression | Object | Intra-cycle weight progression. See details. |
requiredInputs — RequiredInput
Define what values the user enters when generating the program (1RM, KB weight, etc.).
| Field | Type | Description |
|---|---|---|
| key | String | Unique key. No spaces. E.g. bench1RM, kbWeight. |
| labelCs | String | Label in Czech displayed to the user. |
| labelEn | String | Label in English. |
| type | Enum | WEIGHT_INPUT = free numeric input. WEIGHT_CHOICES = selection from predefined values. |
| defaultValue | Float | Default value. |
| choices | Array<Float> | Only for WEIGHT_CHOICES. E.g. [8, 12, 16, 20, 24, 32] for KB. |
| linkedExerciseId | String | Exercise ID for auto-fill from user's maxes. E.g. "bench-press". |
| suffix | String | Unit. Default: "kg". |
Examples
// 1RM input linked to an exercise { "key": "squat1RM", "labelCs": "Dřep 1RM", "labelEn": "Squat 1RM", "type": "WEIGHT_INPUT", "defaultValue": 80.0, "linkedExerciseId": "back-squat", "suffix": "kg" } // KB selection without exercise link { "key": "tguWeight", "labelCs": "TGU kettlebell", "labelEn": "TGU kettlebell", "type": "WEIGHT_CHOICES", "defaultValue": 16.0, "choices": [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48], "suffix": "kg" }
deloadConfig — DeloadConfig
Optional. Defines an automatic deload week within the cycle.
| Field | Type | Description |
|---|---|---|
| deloadWeek | Int | Deload week number (1-based). 0 = no deload. |
| deloadMultiplier | Float | Weight multiplier. 0.6 = 60% of normal weight. Default: 0.6. |
| assistanceSetReduction | Int | How many sets to reduce for assistance exercises. Default: 0. |
{ "deloadWeek": 4, "deloadMultiplier": 0.6, "assistanceSetReduction": 1 }
weeklyProgression — WeeklyWeightProgression
Optional. Intra-cycle progression — weights increase within a cycle (not just between cycles).
| Field | Type | Description |
|---|---|---|
| type | Enum | NONE | LINEAR_PER_WEEK | LINEAR_PER_N_WEEKS |
| incrementPerInterval | Float | Weight increment per interval (kg). Default: 2.5. |
| intervalWeeks | Int | Interval in weeks (only for LINEAR_PER_N_WEEKS). Default: 2. |
// +2.5 kg every 2 weeks { "type": "LINEAR_PER_N_WEEKS", "incrementPerInterval": 2.5, "intervalWeeks": 2 }
ExerciseDefinition
| Field | Type | Description |
|---|---|---|
| exerciseId | String | Exercise ID from the IronPen database. See list. |
| exerciseName | String | Name for offline display. If empty, populated from DB. |
| orderIndex | Int | Exercise order within the day (0-based). |
| exerciseType | Enum | MAIN | ASSISTANCE |
| supersetGroupId | Int? | Superset group number. Exercises with the same number form a superset. null = no superset. |
| isUnilateral | Bool | Unilateral exercise (reps = per side, tonnage ×2). Default: false. |
| emomEnabled | Bool | EMOM mode. Default: false. |
| emomIntervalSeconds | Int | EMOM interval. Default: 60. |
| sets | Array | List of set definitions. See SetDefinition. |
| wavePattern | Object? | Wave progression for this exercise. See details. |
| deloadReps | String? | Alternative reps for the deload week. E.g. "5" instead of "max". |
| deloadIsAmrap | Bool? | AMRAP override for deload. E.g. false for pull-ups on deload. |
SetDefinition
| Field | Type | Description |
|---|---|---|
| reps | String | Number of repetitions. Formats: "5", "5+", "1+1", "8-12", "max". |
| setType | String | MAIN | WARMUP | FSL. Default: "MAIN". |
| weightSource | Object | Where the weight comes from. See WeightSource. |
| isAmrap | Bool | AMRAP set. Default: false. |
| copies | Int | How many times to repeat this set. Default: 1. Range: 1–20. |
copies is a shorthand. {"reps": "5", "copies": 5} is equivalent to five separate sets with reps "5". Useful for 5×5, 3×10, etc.WeightSourceDefinition
| Field | Type | Description |
|---|---|---|
| type | Enum | Weight source type. See table below. |
| value | Float | Value. For PERCENT_TM/1RM: percentage (0.85 = 85%). For FIXED: weight in kg. |
| key | String? | Only for CUSTOM_INPUT: key from requiredInputs. |
| linkedExerciseId | String? | Only for PERCENT_TM/1RM: exerciseId for 1RM lookup. |
| fromIntensity | String? | Only for DERIVED: "HEAVY", "MEDIUM", "LIGHT". |
| multiplier | Float | Multiplier. Default: 1.0. |
WeightSourceType enum
| Type | Description | Required fields |
|---|---|---|
PERCENT_TM | % of Training Max (1RM × trainingMaxPercent) | value, linkedExerciseId |
PERCENT_1RM | % directly from 1RM | value, linkedExerciseId |
PERCENT_TOP_SET | % of top set (ramp sets) | value |
FIXED | Fixed weight in kg | value |
CUSTOM_INPUT | From user input | key |
DERIVED | Derived from another day (HLM) | fromIntensity, multiplier |
BODYWEIGHT | Bodyweight | none |
Examples
// 85% of Training Max for bench press { "type": "PERCENT_TM", "value": 0.85, "linkedExerciseId": "bench-press" } // Fixed 24 kg { "type": "FIXED", "value": 24.0 } // Bodyweight (pull-ups, push-ups) { "type": "BODYWEIGHT" } // From user input "kbWeight" { "type": "CUSTOM_INPUT", "key": "kbWeight" }
WavePatternDefinition
Optional on ExerciseDefinition. Gradual introduction of a new weight over N weeks.
| Field | Type | Description |
|---|---|---|
| startWeightKey | String | Key from requiredInputs for the starting weight. |
| targetWeightKey | String | Key from requiredInputs for the target weight. |
| spreadType | Enum | CENTER_OUT | LEFT_TO_RIGHT | RIGHT_TO_LEFT |
| transitionWeeks | Int | Number of transition weeks. Default: 6. |
// TGU: 5 sets, from 16 kg to 20 kg, center out, over 6 weeks { "startWeightKey": "tguStartWeight", "targetWeightKey": "tguTargetWeight", "spreadType": "CENTER_OUT", "transitionWeeks": 6 }
WEEKLY_FIXED
Same days every week. The simplest type.
"schedule": { "type": "WEEKLY_FIXED", "fixedDays": [ { "dayIndex": 0, "labelCs": "Push", "labelEn": "Push", "exercises": [/* ... */] }, { "dayIndex": 1, "labelCs": "Pull", "labelEn": "Pull", "exercises": [/* ... */] } ] }
ALTERNATING
Alternating variants. The pattern defines the order.
"schedule": { "type": "ALTERNATING", "alternatingPattern": { "pattern": ["A", "B"], "templates": { "A": { "dayIndex": 0, "labelCs": "Trénink A", "exercises": [/* ... */] }, "B": { "dayIndex": 1, "labelCs": "Trénink B", "exercises": [/* ... */] } } } }
["B", "C", "A"] = order B→C→A→B→C→A... Useful when you want the heavy day before the longest rest.WEEKLY_VARYING
Each week is different. For periodized programs (Wendler, TB Operator).
"schedule": { "type": "WEEKLY_VARYING", "varyingWeeks": [ { "weekIndex": 0, "labelCs": "Týden 1 (3×5)", "labelEn": "Week 1 (3×5)", "isDeload": false, "deloadMultiplier": 1.0, "days": [ { "dayIndex": 0, "labelCs": "OHP", "exercises": [/* 65/75/85% */] }, { "dayIndex": 1, "labelCs": "Deadlift", "exercises": [/* ... */] } ] }, { "weekIndex": 3, "labelCs": "Deload", "isDeload": true, "deloadMultiplier": 0.6, "days": [/* ... */] } ] }
HLM
Heavy/Medium/Light. You define the heavy day, medium and light are derived automatically or manually.
"schedule": { "type": "HLM", "hlmDefinition": { "intensityPattern": ["HEAVY", "LIGHT", "MEDIUM"], "heavyDay": { "dayIndex": 0, "labelCs": "Těžký", "exercises": [/* plné váhy */] }, "mediumDayConfig": { "intensityMultiplier": 0.85, // váhy = 85% heavy "volumeMultiplier": 0.75, // série = 75% heavy (4 místo 5) "useCustomDay": false }, "lightDayConfig": { "intensityMultiplier": 0.70, "volumeMultiplier": 0.50, "useCustomDay": false }, "customMediumDay": null, // nebo DayDefinition pokud useCustomDay=true "customLightDay": null } }
LADDER_PROGRESSION
Ladder system with weekly progression of rungs and ladders.
"schedule": { "type": "LADDER_PROGRESSION", "ladderDefinition": { "exercises": [ { "exerciseId": "kb-clean-press", "exerciseName": "KB Clean & Press", "useLadders": true, "weightSource": { "type": "CUSTOM_INPUT", "key": "kbWeight" } }, { "exerciseId": "pull-ups", "useLadders": true, "mirrorLaddersOf": "kb-clean-press", "weightSource": { "type": "BODYWEIGHT" } }, { "exerciseId": "kb-swing", "useLadders": false, "fixedSets": [{ "reps": "10", "copies": 10, "weightSource": { "type": "CUSTOM_INPUT", "key": "kbWeight" } }], "fixedSetsMatchLadderCount": false, "weightSource": { "type": "CUSTOM_INPUT", "key": "kbWeight" } } ], "weeklyProgression": [ { "weekIndex": 0, "maxRung": 3, "ladderCount": 3 }, { "weekIndex": 1, "maxRung": 4, "ladderCount": 4 }, { "weekIndex": 2, "maxRung": 5, "ladderCount": 5 }, { "weekIndex": 3, "maxRung": 5, "ladderCount": 5 } ], "dayIntensity": ["HEAVY", "LIGHT", "MEDIUM"], "heavyMediumLightRungOffset": { "medium": -1, "light": -2 } } }
progressionRules — ProgressionRuleDefinition
Field on the root object. Array of rules for automatic weight progression.
| Field | Type | Description |
|---|---|---|
| exerciseScope | Enum | ALL_MAIN = all main exercises. SPECIFIC = selected only (see exerciseIds). |
| exerciseIds | Array<String> | Only for SPECIFIC: list of exerciseId. |
| evaluationType | Enum | PER_WORKOUT = after each workout. PER_CYCLE = after completing a cycle. |
| successCondition | Object | {"type": "ALL_MAIN_SETS_COMPLETED", "value": 0} |
| onSuccess | Object | Action on success. {"type": "INCREMENT_WEIGHT", "value": 2.5} |
| onFailure | Object | Action on failure. {"type": "REPEAT_WEIGHT", "value": 0} |
| onRepeatedFailure | Object? | Action after N failures. {"failCount": 3, "action": {"type": "DELOAD_PERCENT", "value": 10}} |
// StrongLifts: +2.5 kg per workout, deload after 3 failures { "exerciseScope": "SPECIFIC", "exerciseIds": ["bench-press", "overhead-press", "barbell-rows"], "evaluationType": "PER_WORKOUT", "successCondition": { "type": "ALL_MAIN_SETS_COMPLETED", "value": 0 }, "onSuccess": { "type": "INCREMENT_WEIGHT", "value": 2.5 }, "onFailure": { "type": "REPEAT_WEIGHT", "value": 0 }, "onRepeatedFailure": { "failCount": 3, "action": { "type": "DELOAD_PERCENT", "value": 10 } } }
ActionType enum
| Type | Description | value |
|---|---|---|
NO_CHANGE | Do nothing | ignored |
INCREMENT_WEIGHT | Add fixed weight (kg) | kg increment (2.5, 5.0) |
REPEAT_WEIGHT | Repeat same weight | ignored |
DELOAD_PERCENT | Reduce weight by % | percentage reduction (10 = -10%) |
INCREMENT_TM | Increase Training Max (per cycle) | kg increment on TM |
GENERATE_NEXT_CYCLE | Generate next cycle | ignored |
SuccessCondition types
| Type | Description |
|---|---|
ALL_MAIN_SETS_COMPLETED | All MAIN sets completed |
ALL_REPS_HIT | All planned reps achieved |
AMRAP_MINIMUM | AMRAP set ≥ value reps |
Example: StrongLifts 5×5
Complete template. ALTERNATING A/B, per-workout progression.
{
"version": 1,
"meta": {
"id": "stronglifts-5x5",
"nameCs": "StrongLifts 5×5", "nameEn": "StrongLifts 5×5",
"descriptionCs": "Začátečnický program 3× týdně. Střídání A/B.",
"icon": "🏋️", "tags": ["beginner", "strength"]
},
"config": {
"daysPerWeek": [3], "weeksPerCycle": 4, "maxCycles": 6,
"trainingMaxPercent": 1.0,
"requiredInputs": [
{ "key": "squat1RM", "labelCs": "Dřep 1RM", "labelEn": "Squat 1RM",
"type": "WEIGHT_INPUT", "defaultValue": 60, "linkedExerciseId": "back-squat" },
{ "key": "bench1RM", "labelCs": "Bench 1RM", "labelEn": "Bench 1RM",
"type": "WEIGHT_INPUT", "defaultValue": 40, "linkedExerciseId": "bench-press" },
{ "key": "row1RM", "labelCs": "Row 1RM", "labelEn": "Row 1RM",
"type": "WEIGHT_INPUT", "defaultValue": 40, "linkedExerciseId": "barbell-rows" },
{ "key": "ohp1RM", "labelCs": "OHP 1RM", "labelEn": "OHP 1RM",
"type": "WEIGHT_INPUT", "defaultValue": 30, "linkedExerciseId": "overhead-press" },
{ "key": "dl1RM", "labelCs": "Deadlift 1RM", "labelEn": "Deadlift 1RM",
"type": "WEIGHT_INPUT", "defaultValue": 80, "linkedExerciseId": "deadlift" }
]
},
"schedule": {
"type": "ALTERNATING",
"alternatingPattern": {
"pattern": ["A", "B"],
"templates": {
"A": {
"dayIndex": 0, "labelCs": "Trénink A", "labelEn": "Workout A",
"exercises": [
{ "exerciseId": "back-squat", "orderIndex": 0, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.80, "linkedExerciseId": "back-squat" }, "copies": 5 }] },
{ "exerciseId": "bench-press", "orderIndex": 1, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.80, "linkedExerciseId": "bench-press" }, "copies": 5 }] },
{ "exerciseId": "barbell-rows", "orderIndex": 2, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.80, "linkedExerciseId": "barbell-rows" }, "copies": 5 }] }
]
},
"B": {
"dayIndex": 1, "labelCs": "Trénink B", "labelEn": "Workout B",
"exercises": [
{ "exerciseId": "back-squat", "orderIndex": 0, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.80, "linkedExerciseId": "back-squat" }, "copies": 5 }] },
{ "exerciseId": "overhead-press", "orderIndex": 1, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.80, "linkedExerciseId": "overhead-press" }, "copies": 5 }] },
{ "exerciseId": "deadlift", "orderIndex": 2, "exerciseType": "MAIN",
"sets": [{ "reps": "5", "weightSource": { "type": "PERCENT_1RM", "value": 0.85, "linkedExerciseId": "deadlift" }, "copies": 1 }] }
]
}
}
}
},
"progressionRules": [
{ "exerciseScope": "SPECIFIC",
"exerciseIds": ["back-squat", "bench-press", "barbell-rows", "overhead-press"],
"evaluationType": "PER_WORKOUT",
"successCondition": { "type": "ALL_MAIN_SETS_COMPLETED" },
"onSuccess": { "type": "INCREMENT_WEIGHT", "value": 2.5 },
"onFailure": { "type": "REPEAT_WEIGHT" },
"onRepeatedFailure": { "failCount": 3, "action": { "type": "DELOAD_PERCENT", "value": 10 } } },
{ "exerciseScope": "SPECIFIC",
"exerciseIds": ["deadlift"],
"evaluationType": "PER_WORKOUT",
"successCondition": { "type": "ALL_MAIN_SETS_COMPLETED" },
"onSuccess": { "type": "INCREMENT_WEIGHT", "value": 5.0 },
"onFailure": { "type": "REPEAT_WEIGHT" },
"onRepeatedFailure": { "failCount": 3, "action": { "type": "DELOAD_PERCENT", "value": 10 } } }
]
}
Example: Wendler 5/3/1 (abbreviated)
WEEKLY_VARYING, 4 weeks, only OHP day shown for demonstration. Other days have the same structure with different exercises.
Example: Texas Method (abbreviated)
Modeled as WEEKLY_VARYING (2 unique weeks × 3 days). Odd week has Bench on Volume day, even week has OHP.
exerciseId List
Complete list of 163 exercise IDs supported in IronPen. Use the exact string in the exerciseId field.
Main compound exercises
| ID | Name EN | Name CS |
|---|---|---|
back-squat | Back Squat | Dřep s činkou |
bench-press | Bench Press | Bench press |
deadlift | Deadlift | Mrtvý tah |
overhead-press | Overhead Press | Tlak nad hlavu |
power-clean | Power Clean | Power Clean |
front-squat | Front Squat | Přední dřep |
barbell-rows | Barbell Rows | Přítahy s činkou |
hip-thrust | Hip Thrust | Hip Thrust |
sumo-deadlift | Sumo Deadlift | Sumo mrtvý tah |
romanian-deadlift | Romanian Deadlift | Rumunský mrtvý tah |
Bodyweight exercises
| ID | Name EN |
|---|---|
pull-ups | Pull-ups |
chin-ups | Chin-ups |
push-ups | Push-ups |
dips | Dips |
ring-rows | Ring Rows |
inverted-rows | Inverted Rows |
plank | Plank |
leg-raises | Leg Raises |
Kettlebell exercises
| ID | Name EN |
|---|---|
kb-swing | KB Swing |
kb-clean-press | KB Clean & Press |
tgu | Turkish Get-Up |
kb-snatch | KB Snatch |
goblet-squat | Goblet Squat |
kb-front-squat | KB Front Squat |
exercises.json file exportable from the app, or in the exercise database under "Exercise List".Validation Rules
The app validates JSON on import. Most common errors:
| Rule | Error message |
|---|---|
| At least one of nameCs/nameEn must be non-empty | Template name is required |
| meta.id non-empty, no spaces | Template ID is required |
| daysPerWeek: at least 1 value, 1-7 | daysPerWeek must be 1-7 |
| weeksPerCycle: 1-52 | weeksPerCycle must be 1-52 |
| trainingMaxPercent: 0.5-1.0 | trainingMaxPercent must be 0.5-1.0 |
| Each exercise must have at least 1 set | Exercise has no sets |
| Max 30 sets per exercise | Exercise has >30 sets |
| Max 15 exercises per day | Day has >15 exercises |
| PERCENT_TM/1RM: value 0.05-1.5 | Weight percentage out of range |
| CUSTOM_INPUT: key exists in requiredInputs | CUSTOM_INPUT key not in requiredInputs |
| copies: 1-20 | Set copies must be 1-20 |
| Schedule type matches populated fields | WEEKLY_FIXED requires fixedDays |