Workouts¶
Beta Functionality
The workouts API is in beta and breaking changes can land at short notice. If you plan to use this API in production, get in direct contact with us so we can warn you before a change ships and help you migrate. Email [email protected] before integrating, not after.
SweatStack workouts are planned training sessions: a structured prescription tied to a future start date. They're distinct from activities, which are recorded sessions. A workout is what the athlete plans to do. An activity is what they actually did.
When you create a scheduled workout, SweatStack stores it and pushes it to the athlete's connected platforms (for example Garmin Connect) so users can execute them directly from their wearables.
What you can do today¶
- Create a workout scheduled for a specific date and time.
- List the scheduled workouts for an athlete.
- Read a single scheduled workout by id.
What will be added later¶
- Updating and deleting workouts, also after they are synced to integrations
- Workout library workouts (no
startdate, used as templates for later use)
Structured Workout Format (SWF)¶
The workout content uses the Structured Workout Format, an open JSON schema for prescribing structured workouts. At the moment, SweatStack accepts a subset of the format:
| Aspect | Currently supported |
|---|---|
| Sports | running (and its sub-sports, e.g. running.road, running.track) |
| Intensity quantity | speed (m/s) |
| Volume quantity | duration (seconds) and distance (meters) |
| Shapes | constant, range, ramp, zone |
| References | absolute values and ParameterRef (named placeholders resolved at fanout time) |
Anything outside this set is rejected at creation with a structured 422 error. The list grows as SweatStack expands what it can fan out (cycling with power, etc.). Get in touch if you have a usecase that is not yet supported.
Create a scheduled workout¶
POST /api/v1/workouts/schedule accepts a body with three top-level fields: swf, start, and an optional parameters map.
curl -X POST "https://app.sweatstack.no/api/v1/workouts/schedule" \
-H "Authorization: Bearer {your_access_token}" \
-H "Content-Type: application/json" \
-d '{
"swf": {
"version": "0.3.0",
"title": "5K with 4x1K Intervals",
"sport": "running",
"content": [
{
"type": "step",
"effort": "work",
"volume": {"type": "constant", "quantity": "distance", "value": 5000},
"intensity": {
"type": "range",
"quantity": "speed",
"min": {"percent": 70, "of": "threshold_pace"},
"max": {"percent": 80, "of": "threshold_pace"}
}
},
{
"type": "repeat",
"count": 4,
"content": [
{
"type": "step",
"effort": "work",
"volume": {"type": "constant", "quantity": "distance", "value": 1000},
"intensity": {
"type": "constant",
"quantity": "speed",
"value": {"percent": 110, "of": "threshold_pace"}
}
},
{
"type": "step",
"effort": "rest",
"volume": {"type": "constant", "quantity": "duration", "value": 90}
}
]
}
]
},
"start": "2026-05-25T07:00:00+02:00",
"parameters": {"threshold_pace": 4.45}
}'
startis a TZ-aware ISO 8601 datetime.sportis read from the SWF.parametersresolvesParameterRefs in the SWF. Every parameter referenced by the workout must be present here, or the request is rejected. For workouts with only absolute values, you can omitparameters.
Validation errors¶
Validation runs against a single SweatStack-level strategy at creation time. Failures return 422 Unprocessable Entity with a structured detail array. Each entry has a code and a path into the workout tree where the problem lives:
{
"detail": [
{"code": "unsupported_sport", "message": "Sport 'cycling' is not supported", "path": []}
]
}
Common codes:
| Code | Meaning |
|---|---|
unsupported_sport |
Sport isn't accepted yet (only running and sub-sports in v1). |
unsupported_intensity |
Intensity quantity outside the supported set (only speed in v1). |
unsupported_volume |
Volume quantity outside the supported set. |
unsupported_shape |
Shape (range/ramp/zone) not supported. |
missing_parameters |
The workout references ParameterRefs the request didn't provide. detail[0].missing lists them. |
For more details and development tools for creating and validating SWF workouts, see https://structuredworkoutformat.dev.
Success response¶
{
"id": "01JW3K...",
"sport": "running",
"start": "2026-05-25T07:00:00+02:00",
"swf": { "..." },
"parameters": {"threshold_pace": 4.45},
"application_id": "01JW3J...",
"application_name": "My App"
}
application_id/application_nameidentify the third-party app that created this workout.
Fanout: how the workout reaches the athlete¶
After SweatStack persists the workout, an asynchronous task pushes it to the athlete's connected integrations. The push runs in the background and typically completes within seconds.
Fanout status is not returned on the API response. Persistent issues (like missing permission to push workouts to Garmin) surface to the athlete directly through a warning in their SweatStack profile, which can also be retrieved through the profile-status API endpoint.
See also¶
- API reference: Workouts. Every endpoint, request, and response schema, generated from the live OpenAPI spec.
- Activities. The recorded counterpart of a workout.
- Integrations. The Garmin connection that workouts fan out to.
- Structured Workout Format. The open spec for the SWF payload.