Workout Templates reference
List, read, save and delete the user's workout plans: exercises with planned sets that the app starts a workout from.
The DailyGoal API is not available on the Free plan. It works with a paid plan or during a free trial. See plans.
Operations
list_workout_templates: List workout templatesget_workout_template: Get workout templatesave_workout_template: Save workout templatedelete_workout_template: Delete workout template
list_workout_templates
GET https://api.dailygoal.fit/v1/workout-templates
MCP tool list_workout_templates · Read-only
List the user's saved workout templates, the plans the app starts a workout from, newest first, with pagination. Summaries name the exercises but have no sets; use get_workout_template for those. For DailyGoal's built-in plans use list_workout_presets; for workouts already done use list_workouts.
Input
| Field | Type | Description |
|---|---|---|
| queryoptional | string | Words in the template name. Results then come in relevance order instead of newest first. |
| limitoptional | integer | Page size. Defaults to 20. |
| cursoroptional | string | nextCursor from the previous page, with the same query. |
Output
| Field | Type | Description |
|---|---|---|
| templates | object[] | |
| templates[].id | string | Template id for get_workout_template, save_workout_template and delete_workout_template. |
| templates[].name | string | |
| templates[].notesoptional | string | |
| templates[].exerciseCount | integer | |
| templates[].exerciseNames | string[] | Exercise names in template order. |
| templates[].isTruncatedoptional | true | Present and true when the template was saved with more than 30 exercises, so this result lists only 30. Such a template can only be deleted. |
| hasMore | boolean | True when more templates match. Pass nextCursor to get them. |
| nextCursor | string | null |
Example request
curl "https://api.dailygoal.fit/v1/workout-templates?limit=10" \
-H "Authorization: Bearer $DAILYGOAL_API_TOKEN"{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_workout_templates",
"arguments": {
"limit": 10
}
}
}Example response
Synthetic data. REST returns this object as the body; MCP returns it as structuredContent.
{
"templates": [
{
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3",
"name": "Push day",
"notes": "Heavy week",
"exerciseCount": 2,
"exerciseNames": [
"Barbell Bench Press",
"Overhead Press"
]
}
],
"hasMore": false,
"nextCursor": null
}Errors
unauthorized(401)origin_not_allowed(403)misdirected_request(421)subscription_required(403)rate_limited(429)validation_failed(400)internal_error(500)
get_workout_template
GET https://api.dailygoal.fit/v1/workout-templates/detail
MCP tool get_workout_template · Read-only
Get one saved workout template with every exercise and its planned sets. Use list_workout_templates to find the id. For a workout the user already did, use get_workout.
Input
| Field | Type | Description |
|---|---|---|
| id | string | Template id from list_workout_templates or save_workout_template. |
Output
| Field | Type | Description |
|---|---|---|
| id | string | Template id for get_workout_template, save_workout_template and delete_workout_template. |
| name | string | |
| notesoptional | string | |
| exercises | object[] | |
| exercises[].exerciseId | string | |
| exercises[].name | string | |
| exercises[].notesoptional | string | |
| exercises[].sets | object[] | |
| exercises[].sets[].setNumber | integer | |
| exercises[].sets[].setType | "warmup" | "working" | |
| exercises[].sets[].repsoptional | integer | |
| exercises[].sets[].durationSecondsoptional | number | |
| exercises[].sets[].distanceMetersoptional | number | |
| exercises[].sets[].holdSecondsoptional | number | |
| exercises[].sets[].restSecondsoptional | number | Rest after this set, in seconds. |
| exercises[].sets[].intensityoptional | number | Planned effort from 0 to 10. |
| exercises[].sets[].weightoptional | object | Planned load in the user's preferred strength unit. |
| exercises[].sets[].weight.value | number | |
| exercises[].sets[].weight.unit | "kg" | "lb" | |
| exercises[].sets[].weightKgoptional | number | Canonical planned load in kilograms. |
| isTruncatedoptional | true | Present and true when the template was saved with more than 30 exercises, so this result lists only 30. Such a template can only be deleted. |
Example request
curl "https://api.dailygoal.fit/v1/workout-templates/detail?id=kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3" \
-H "Authorization: Bearer $DAILYGOAL_API_TOKEN"{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_workout_template",
"arguments": {
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3"
}
}
}Example response
Synthetic data. REST returns this object as the body; MCP returns it as structuredContent.
{
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3",
"name": "Push day",
"notes": "Heavy week",
"exercises": [
{
"exerciseId": "jx71q4w7e0r3t6y9u2i5o8p1a4s7d0f3",
"name": "Barbell Bench Press",
"sets": [
{
"setNumber": 1,
"setType": "warmup",
"weight": {
"value": 40,
"unit": "kg"
},
"weightKg": 40,
"reps": 10
},
{
"setNumber": 2,
"setType": "working",
"weight": {
"value": 80,
"unit": "kg"
},
"weightKg": 80,
"reps": 5,
"restSeconds": 180
}
]
},
{
"exerciseId": "jx73e6r9t2y5u8i1o4p7a0s3d6f9g2h5",
"name": "Overhead Press",
"sets": [
{
"setNumber": 1,
"setType": "working",
"weight": {
"value": 40,
"unit": "kg"
},
"weightKg": 40,
"reps": 8,
"restSeconds": 120
}
]
}
]
}Errors
unauthorized(401)origin_not_allowed(403)misdirected_request(421)subscription_required(403)rate_limited(429)validation_failed(400)not_found(404)internal_error(500)
save_workout_template
POST https://api.dailygoal.fit/v1/workout-templates
MCP tool save_workout_template · Changes data · Destructive · Accepts Idempotency-Key
Create a workout template, or replace one by passing its id: name, notes and the whole list of exercises with planned sets. Get exercise ids from search_exercises, or from list_workout_presets to copy a built-in plan. It records no workout; to log one the user did, use log_workout.
Input
| Field | Type | Description |
|---|---|---|
| idoptional | string | The template to update. Omit it to create a new template. |
| name | string | |
| notesoptional | string | Omitted notes are cleared on update. |
| exercises | object[] | |
| exercises[].exerciseIdoptional | string | Exercise id from search_exercises or list_workout_presets. Preferred. |
| exercises[].nameoptional | string | Exact catalogue name, used when exerciseId is absent. |
| exercises[].notesoptional | string | |
| exercises[].sets | object[] | |
| exercises[].sets[].setTypeoptional | "warmup" | "working" | Defaults to working. |
| exercises[].sets[].weightoptional | object | A load with its unit. Stored as kilograms. |
| exercises[].sets[].weight.value | number | |
| exercises[].sets[].weight.unit | "kg" | "lb" | |
| exercises[].sets[].repsoptional | integer | |
| exercises[].sets[].durationSecondsoptional | number | |
| exercises[].sets[].distanceMetersoptional | number | |
| exercises[].sets[].holdSecondsoptional | number | |
| exercises[].sets[].restSecondsoptional | integer | Rest after this set, in seconds. Defaults to none. |
| exercises[].sets[].intensityoptional | number | Planned effort from 0 to 10. |
| idempotency_keyoptional | string | Optional. A unique value for this create, for example a UUID. Retrying with the same key and arguments within 24 hours returns the first result instead of creating a duplicate. |
Output
| Field | Type | Description |
|---|---|---|
| created | boolean | True when this call created the template, false when it updated one. |
| template | object | |
| template.id | string | Template id for get_workout_template, save_workout_template and delete_workout_template. |
| template.name | string | |
| template.notesoptional | string | |
| template.exercises | object[] | |
| template.exercises[].exerciseId | string | |
| template.exercises[].name | string | |
| template.exercises[].notesoptional | string | |
| template.exercises[].sets | object[] | |
| template.exercises[].sets[].setNumber | integer | |
| template.exercises[].sets[].setType | "warmup" | "working" | |
| template.exercises[].sets[].repsoptional | integer | |
| template.exercises[].sets[].durationSecondsoptional | number | |
| template.exercises[].sets[].distanceMetersoptional | number | |
| template.exercises[].sets[].holdSecondsoptional | number | |
| template.exercises[].sets[].restSecondsoptional | number | Rest after this set, in seconds. |
| template.exercises[].sets[].intensityoptional | number | Planned effort from 0 to 10. |
| template.exercises[].sets[].weightoptional | object | Planned load in the user's preferred strength unit. |
| template.exercises[].sets[].weight.value | number | |
| template.exercises[].sets[].weight.unit | "kg" | "lb" | |
| template.exercises[].sets[].weightKgoptional | number | Canonical planned load in kilograms. |
| template.isTruncatedoptional | true | Present and true when the template was saved with more than 30 exercises, so this result lists only 30. Such a template can only be deleted. |
Example request
curl -X POST "https://api.dailygoal.fit/v1/workout-templates" \
-H "Authorization: Bearer $DAILYGOAL_API_TOKEN" \
-H "Idempotency-Key: 3f1c9a52-7d4e-4b8a-9e21-5c6d7e8f9a01" \
-H "Content-Type: application/json" \
-d '{"name":"Push day","notes":"Heavy week","exercises":[{"exerciseId":"jx71q4w7e0r3t6y9u2i5o8p1a4s7d0f3","sets":[{"setType":"warmup","weight":{"value":40,"unit":"kg"},"reps":10},{"weight":{"value":80,"unit":"kg"},"reps":5,"restSeconds":180}]},{"exerciseId":"jx73e6r9t2y5u8i1o4p7a0s3d6f9g2h5","sets":[{"weight":{"value":40,"unit":"kg"},"reps":8,"restSeconds":120}]}]}'{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "save_workout_template",
"arguments": {
"name": "Push day",
"notes": "Heavy week",
"exercises": [
{
"exerciseId": "jx71q4w7e0r3t6y9u2i5o8p1a4s7d0f3",
"sets": [
{
"setType": "warmup",
"weight": {
"value": 40,
"unit": "kg"
},
"reps": 10
},
{
"weight": {
"value": 80,
"unit": "kg"
},
"reps": 5,
"restSeconds": 180
}
]
},
{
"exerciseId": "jx73e6r9t2y5u8i1o4p7a0s3d6f9g2h5",
"sets": [
{
"weight": {
"value": 40,
"unit": "kg"
},
"reps": 8,
"restSeconds": 120
}
]
}
]
}
}
}Example response
Synthetic data. REST returns this object as the body; MCP returns it as structuredContent.
{
"created": true,
"template": {
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3",
"name": "Push day",
"notes": "Heavy week",
"exercises": [
{
"exerciseId": "jx71q4w7e0r3t6y9u2i5o8p1a4s7d0f3",
"name": "Barbell Bench Press",
"sets": [
{
"setNumber": 1,
"setType": "warmup",
"weight": {
"value": 40,
"unit": "kg"
},
"weightKg": 40,
"reps": 10
},
{
"setNumber": 2,
"setType": "working",
"weight": {
"value": 80,
"unit": "kg"
},
"weightKg": 80,
"reps": 5,
"restSeconds": 180
}
]
},
{
"exerciseId": "jx73e6r9t2y5u8i1o4p7a0s3d6f9g2h5",
"name": "Overhead Press",
"sets": [
{
"setNumber": 1,
"setType": "working",
"weight": {
"value": 40,
"unit": "kg"
},
"weightKg": 40,
"reps": 8,
"restSeconds": 120
}
]
}
]
}
}Errors
unauthorized(401)origin_not_allowed(403)misdirected_request(421)subscription_required(403)rate_limited(429)validation_failed(400)not_found(404)idempotency_conflict(409)internal_error(500)
delete_workout_template
DELETE https://api.dailygoal.fit/v1/workout-templates
MCP tool delete_workout_template · Changes data · Destructive
Delete one saved workout template. Workouts already started from it are kept. This cannot be undone. To delete a workout the user did, use delete_workout.
Input
| Field | Type | Description |
|---|---|---|
| id | string | Template id from list_workout_templates or save_workout_template. |
Output
| Field | Type | Description |
|---|---|---|
| id | string | |
| deleted | true |
Example request
curl -X DELETE "https://api.dailygoal.fit/v1/workout-templates?id=kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3" \
-H "Authorization: Bearer $DAILYGOAL_API_TOKEN"{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "delete_workout_template",
"arguments": {
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3"
}
}
}Example response
Synthetic data. REST returns this object as the body; MCP returns it as structuredContent.
{
"id": "kt71a4s7d0f3g6h9j2k5l8z1x4c7v0b3",
"deleted": true
}Errors
unauthorized(401)origin_not_allowed(403)misdirected_request(421)subscription_required(403)rate_limited(429)validation_failed(400)not_found(404)internal_error(500)