Skip to content

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:

performance_summary_id pydantic-field

performance_summary_id = 'unknown'

Unique identifier for this performance summary

booking_id pydantic-field

booking_id

The booking id for the new bookings endpoint.

class_uuid pydantic-field

class_uuid = None

Used by the ratings endpoint - seems to fall off after a few months

coach pydantic-field

coach = None

First name of the coach

class_history_uuid property

class_history_uuid

Alias for performance_summary_id.

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.