Workout
Workout
pydantic-model
¶
Bases: ApiMixin, OtfItemBase
Represents a workout - combines the performance summary, data from the new bookings endpoint, and telemetry data.
The final product contains all the performance summary data, the detailed data over time, as well as the class, coach, studio, and rating data from the new endpoint.
This should match the data that is shown in the OTF app after a workout.
Show JSON schema:
{
"$defs": {
"Address": {
"description": "Address associated with a studio in the v2 bookings endpoint.",
"properties": {
"line1": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Line1"
},
"line2": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Line2"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "City"
},
"postal_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Postal Code"
},
"state": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "State"
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Country"
},
"physicalRegion": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Physicalregion"
},
"physicalCountryId": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Physicalcountryid"
}
},
"title": "Address",
"type": "object"
},
"BookingV2Class": {
"description": "Class details from the v2 bookings endpoint.",
"properties": {
"id": {
"description": "Matches the `class_id` attribute of the OtfClass model",
"title": "Id",
"type": "string"
},
"name": {
"description": "The name of the class.",
"title": "Name",
"type": "string"
},
"type": {
"allOf": [
{
"$ref": "#/$defs/ClassType"
}
],
"description": "The high-level class format category."
},
"starts_at_local": {
"description": "The start time of the class. Reflects local time, but the object does not have a timezone.",
"format": "date-time",
"title": "Starts At Local",
"type": "string"
},
"studio": {
"anyOf": [
{
"$ref": "#/$defs/BookingV2Studio"
},
{
"type": "null"
}
],
"default": null,
"description": "The studio where the class takes place."
},
"coach": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First name of the coach leading the class.",
"title": "Coach"
},
"ot_base_class_uuid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Only present when class is ratable",
"title": "Ot Base Class Uuid"
},
"starts_at": {
"anyOf": [
{
"format": "date-time",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Starts At"
}
},
"required": [
"id",
"name",
"type",
"starts_at_local"
],
"title": "BookingV2Class",
"type": "object"
},
"BookingV2Studio": {
"description": "Studio details from the v2 bookings endpoint.",
"properties": {
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Phone"
},
"latitude": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Latitude"
},
"longitude": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Longitude"
},
"id": {
"description": "Unique identifier for the studio.",
"title": "Id",
"type": "string"
},
"name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Name of the studio.",
"title": "Name"
},
"time_zone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "IANA time zone of the studio.",
"title": "Time Zone"
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Contact email for the studio.",
"title": "Email"
},
"address": {
"anyOf": [
{
"$ref": "#/$defs/Address"
},
{
"type": "null"
}
],
"default": null,
"description": "Physical address of the studio."
},
"currency_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Currency Code"
},
"mbo_studio_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "MindBody attr",
"title": "Mbo Studio Id"
}
},
"required": [
"id"
],
"title": "BookingV2Studio",
"type": "object"
},
"ClassType": {
"description": "High-level classification of OTF class formats.",
"enum": [
"ORANGE_60",
"ORANGE_90",
"OTHER",
"STRENGTH_50",
"TREAD_50"
],
"title": "ClassType",
"type": "string"
},
"HeartRate": {
"description": "Heart rate statistics from a workout.",
"properties": {
"max_hr": {
"description": "Member's configured max heart rate.",
"title": "Max Hr",
"type": "integer"
},
"peak_hr": {
"description": "Highest heart rate reached during the workout.",
"title": "Peak Hr",
"type": "integer"
},
"peak_hr_percent": {
"description": "Peak HR as a percentage of max HR.",
"title": "Peak Hr Percent",
"type": "integer"
},
"avg_hr": {
"description": "Average heart rate during the workout.",
"title": "Avg Hr",
"type": "integer"
},
"avg_hr_percent": {
"description": "Average HR as a percentage of max HR.",
"title": "Avg Hr Percent",
"type": "integer"
}
},
"required": [
"max_hr",
"peak_hr",
"peak_hr_percent",
"avg_hr",
"avg_hr_percent"
],
"title": "HeartRate",
"type": "object"
},
"PerformanceMetric": {
"description": "A single performance metric with display and raw values.",
"properties": {
"display_value": {
"description": "Formatted value for display (e.g. '6:30').",
"title": "Display Value"
},
"display_unit": {
"description": "Unit label for display (e.g. 'min/mi', 'mph').",
"title": "Display Unit",
"type": "string"
},
"metric_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "integer"
}
],
"description": "The raw value of the metric, as a float or int. When time this reflects seconds.",
"title": "Metric Value"
}
},
"required": [
"display_value",
"display_unit",
"metric_value"
],
"title": "PerformanceMetric",
"type": "object"
},
"Rating": {
"description": "A rating given by a member for a class or coach.",
"properties": {
"id": {
"description": "Unique identifier for the rating.",
"title": "Id",
"type": "string"
},
"description": {
"description": "Human-readable label for the rating level.",
"title": "Description",
"type": "string"
},
"value": {
"description": "Numeric rating value.",
"title": "Value",
"type": "integer"
}
},
"required": [
"id",
"description",
"value"
],
"title": "Rating",
"type": "object"
},
"RowData": {
"description": "Rower telemetry data for a single point in time.",
"properties": {
"rowSpeed": {
"description": "Current rowing speed.",
"title": "Rowspeed",
"type": "number"
},
"rowPps": {
"description": "Rowing power per stroke.",
"title": "Rowpps",
"type": "number"
},
"rowSpm": {
"description": "Rowing strokes per minute.",
"title": "Rowspm",
"type": "number"
},
"aggRowDistance": {
"description": "Cumulative rowing distance.",
"title": "Aggrowdistance",
"type": "integer"
},
"rowPace": {
"description": "Current rowing pace.",
"title": "Rowpace",
"type": "integer"
}
},
"required": [
"rowSpeed",
"rowPps",
"rowSpm",
"aggRowDistance",
"rowPace"
],
"title": "RowData",
"type": "object"
},
"Rower": {
"description": "Rower-specific performance data from a workout.",
"properties": {
"avg_pace": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average pace during the workout segment."
},
"avg_speed": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average speed during the workout segment."
},
"max_pace": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Fastest pace achieved."
},
"max_speed": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Maximum speed achieved."
},
"moving_time": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Total time spent actively moving."
},
"total_distance": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Total distance covered."
},
"avg_cadence": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average strokes per minute."
},
"avg_power": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average power output in watts."
},
"max_cadence": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Maximum strokes per minute achieved."
}
},
"required": [
"avg_pace",
"avg_speed",
"max_pace",
"max_speed",
"moving_time",
"total_distance",
"avg_cadence",
"avg_power",
"max_cadence"
],
"title": "Rower",
"type": "object"
},
"Telemetry": {
"description": "Full telemetry data for a workout, including time-series heart rate and equipment data.",
"properties": {
"memberUuid": {
"description": "Unique identifier for the member.",
"title": "Memberuuid",
"type": "string"
},
"classHistoryUuid": {
"description": "The same as performance_summary_id.",
"title": "Classhistoryuuid",
"type": "string"
},
"classStartTime": {
"anyOf": [
{
"format": "date-time",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "When the class started.",
"title": "Classstarttime"
},
"maxHr": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Member's max heart rate.",
"title": "Maxhr"
},
"zones": {
"anyOf": [
{
"$ref": "#/$defs/Zones"
},
{
"type": "null"
}
],
"default": null,
"description": "The zones associated with the telemetry."
},
"windowSize": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Telemetry sampling window size in seconds.",
"title": "Windowsize"
},
"telemetry": {
"description": "Time-series telemetry data points.",
"items": {
"$ref": "#/$defs/TelemetryItem"
},
"title": "Telemetry",
"type": "array"
}
},
"required": [
"memberUuid",
"classHistoryUuid",
"classHistoryUuid"
],
"title": "Telemetry",
"type": "object"
},
"TelemetryItem": {
"description": "A single telemetry data point captured during a workout.",
"properties": {
"relativeTimestamp": {
"description": "Seconds since the start of the class.",
"title": "Relativetimestamp",
"type": "integer"
},
"hr": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Heart rate in BPM at this point in time.",
"title": "Hr"
},
"aggSplats": {
"description": "Cumulative splat points at this time.",
"title": "Aggsplats",
"type": "integer"
},
"aggCalories": {
"description": "Cumulative calories burned at this time.",
"title": "Aggcalories",
"type": "integer"
},
"timestamp": {
"anyOf": [
{
"format": "date-time",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The timestamp of the telemetry item, calculated from the class start time and relative timestamp.",
"title": "Timestamp"
},
"treadData": {
"anyOf": [
{
"$ref": "#/$defs/TreadData"
},
{
"type": "null"
}
],
"default": null,
"description": "Treadmill data, present when on the treadmill."
},
"rowData": {
"anyOf": [
{
"$ref": "#/$defs/RowData"
},
{
"type": "null"
}
],
"default": null,
"description": "Rower data, present when on the rower."
}
},
"required": [
"relativeTimestamp",
"aggSplats",
"aggCalories"
],
"title": "TelemetryItem",
"type": "object"
},
"TreadData": {
"description": "Treadmill telemetry data for a single point in time.",
"properties": {
"treadSpeed": {
"description": "Current treadmill speed.",
"title": "Treadspeed",
"type": "number"
},
"treadIncline": {
"description": "Current treadmill incline.",
"title": "Treadincline",
"type": "number"
},
"aggTreadDistance": {
"description": "Cumulative treadmill distance.",
"title": "Aggtreaddistance",
"type": "integer"
}
},
"required": [
"treadSpeed",
"treadIncline",
"aggTreadDistance"
],
"title": "TreadData",
"type": "object"
},
"Treadmill": {
"description": "Treadmill-specific performance data from a workout.",
"properties": {
"avg_pace": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average pace during the workout segment."
},
"avg_speed": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average speed during the workout segment."
},
"max_pace": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Fastest pace achieved."
},
"max_speed": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Maximum speed achieved."
},
"moving_time": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Total time spent actively moving."
},
"total_distance": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Total distance covered."
},
"avg_incline": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Average incline during the treadmill segment."
},
"elevation_gained": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Total elevation gained."
},
"max_incline": {
"allOf": [
{
"$ref": "#/$defs/PerformanceMetric"
}
],
"description": "Maximum incline achieved."
}
},
"required": [
"avg_pace",
"avg_speed",
"max_pace",
"max_speed",
"moving_time",
"total_distance",
"avg_incline",
"elevation_gained",
"max_incline"
],
"title": "Treadmill",
"type": "object"
},
"Zone": {
"description": "A heart rate zone defined by a BPM range.",
"properties": {
"startBpm": {
"description": "Lower bound BPM for this zone.",
"title": "Startbpm",
"type": "integer"
},
"endBpm": {
"description": "Upper bound BPM for this zone.",
"title": "Endbpm",
"type": "integer"
}
},
"required": [
"startBpm",
"endBpm"
],
"title": "Zone",
"type": "object"
},
"ZoneTimeMinutes": {
"description": "Time spent in each heart rate zone during a workout, measured in minutes.",
"properties": {
"gray": {
"description": "Minutes in the gray (rest) zone.",
"title": "Gray",
"type": "integer"
},
"blue": {
"description": "Minutes in the blue (light effort) zone.",
"title": "Blue",
"type": "integer"
},
"green": {
"description": "Minutes in the green (base pace) zone.",
"title": "Green",
"type": "integer"
},
"orange": {
"description": "Minutes in the orange (push pace) zone.",
"title": "Orange",
"type": "integer"
},
"red": {
"description": "Minutes in the red (all-out) zone.",
"title": "Red",
"type": "integer"
}
},
"required": [
"gray",
"blue",
"green",
"orange",
"red"
],
"title": "ZoneTimeMinutes",
"type": "object"
},
"Zones": {
"description": "The five OTF heart rate zones (gray, blue, green, orange, red) with their BPM ranges.",
"properties": {
"gray": {
"allOf": [
{
"$ref": "#/$defs/Zone"
}
],
"description": "Rest/very light effort zone."
},
"blue": {
"allOf": [
{
"$ref": "#/$defs/Zone"
}
],
"description": "Light effort zone."
},
"green": {
"allOf": [
{
"$ref": "#/$defs/Zone"
}
],
"description": "Moderate effort (base pace) zone."
},
"orange": {
"allOf": [
{
"$ref": "#/$defs/Zone"
}
],
"description": "High effort (push pace) zone, earns splat points."
},
"red": {
"allOf": [
{
"$ref": "#/$defs/Zone"
}
],
"description": "Maximum effort (all-out) zone, earns splat points."
}
},
"required": [
"gray",
"blue",
"green",
"orange",
"red"
],
"title": "Zones",
"type": "object"
}
},
"description": "Represents a workout - combines the performance summary, data from the new bookings endpoint, and telemetry data.\n\nThe final product contains all the performance summary data, the detailed data over time, as well as the class,\ncoach, studio, and rating data from the new endpoint.\n\nThis should match the data that is shown in the OTF app after a workout.",
"properties": {
"id": {
"default": "unknown",
"description": "Unique identifier for this performance summary",
"title": "Id",
"type": "string"
},
"booking_id": {
"description": "The booking id for the new bookings endpoint.",
"title": "Booking Id",
"type": "string"
},
"class_uuid": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Used by the ratings endpoint - seems to fall off after a few months",
"title": "Class Uuid"
},
"coach": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "First name of the coach",
"title": "Coach"
},
"ratable": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"title": "Ratable"
},
"calories_burned": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Calories Burned"
},
"splat_points": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Splat Points"
},
"step_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Step Count"
},
"zone_time_minutes": {
"anyOf": [
{
"$ref": "#/$defs/ZoneTimeMinutes"
},
{
"type": "null"
}
],
"default": null
},
"heart_rate": {
"anyOf": [
{
"$ref": "#/$defs/HeartRate"
},
{
"type": "null"
}
],
"default": null
},
"active_time_seconds": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"title": "Active Time Seconds"
},
"rower_data": {
"anyOf": [
{
"$ref": "#/$defs/Rower"
},
{
"type": "null"
}
],
"default": null
},
"treadmill_data": {
"anyOf": [
{
"$ref": "#/$defs/Treadmill"
},
{
"type": "null"
}
],
"default": null
},
"class_rating": {
"anyOf": [
{
"$ref": "#/$defs/Rating"
},
{
"type": "null"
}
],
"default": null
},
"coach_rating": {
"anyOf": [
{
"$ref": "#/$defs/Rating"
},
{
"type": "null"
}
],
"default": null
},
"otf_class": {
"$ref": "#/$defs/BookingV2Class"
},
"studio": {
"$ref": "#/$defs/BookingV2Studio"
},
"telemetry": {
"anyOf": [
{
"$ref": "#/$defs/Telemetry"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"booking_id",
"otf_class",
"studio"
],
"title": "Workout",
"type": "object"
}
Fields:
-
_api(Otf) -
performance_summary_id(str) -
booking_id(str) -
class_uuid(str | None) -
coach(str | None) -
ratable(bool | None) -
calories_burned(int | None) -
splat_points(int | None) -
step_count(int | None) -
zone_time_minutes(ZoneTimeMinutes | None) -
heart_rate(HeartRate | None) -
active_time_seconds(int | None) -
rower_data(Rower | None) -
treadmill_data(Treadmill | None) -
class_rating(Rating | None) -
coach_rating(Rating | None) -
otf_class(BookingV2Class) -
studio(BookingV2Studio) -
telemetry(Telemetry | None)
performance_summary_id
pydantic-field
¶
performance_summary_id = 'unknown'
Unique identifier for this performance summary
class_uuid
pydantic-field
¶
class_uuid = None
Used by the ratings endpoint - seems to fall off after a few months
rate ¶
rate(class_rating, coach_rating)
Rate the class and coach for this workout.
The class rating must be 0, 1, 2, or 3. 0 is the same as dismissing the prompt to rate the class/coach. 1 - 3 is a range from bad to good.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
class_rating
|
Literal[0, 1, 2, 3]
|
Rating for the class. |
required |
coach_rating
|
Literal[0, 1, 2, 3]
|
Rating for the coach. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the API instance is not set. |
AlreadyRatedError
|
If the performance summary is already rated. |
ClassNotRatableError
|
If the performance summary is not rateable. |