Skip to content

Changelog

0.19.0 (2026-05-10)

⚠ BREAKING CHANGES

  • cancel_booking no longer accepts BookingV2 objects and cancel_booking_new no longer accepts Booking objects.

Code Refactoring

  • comprehensive code quality cleanup from WTF audit (#130) (2271881)

0.18.0 (2026-05-10)

⚠ BREAKING CHANGES

  • TotalBodyWeight renamed to TotalBodyWater, total_body_weight field renamed to total_body_water, total_body_weight_details renamed to total_body_water_details, OutsideSchedulingWindowError now inherits from BookingError instead of OtfError

Documentation

  • complete documentation overhaul with MkDocs-Material (#127) (daef89e)

0.17.0 (2026-05-09)

Features

  • add diagnostic logging for silent failures and empty API responses (#119) (bc4e853)
  • bookings: detect waitlisted V2 bookings via waitlist_position field (#125) (461b517)

Bug Fixes

  • cancel_booking crash on BookingV2 and missing class_uuid in get_workout_from_booking (#124) (f525d1a)

0.16.0 (2026-04-28)

⚠ BREAKING CHANGES

  • removed deprecated flat methods on Otf class (e.g., otf.book_class()). Use the domain-scoped API instead (e.g., otf.bookings.book_class()).

Features

  • add field validators and relative descriptor properties to BodyCompositionData (0c1b489)
  • add PII anonymization pipeline with real-time capture mode (#109) (c2c381e)
  • api.py, auth.py: add refresh callback functionality to handle token refresh events (e4dacc2)
  • api.py: add exclude_checkedin parameter to get_bookings method to filter out checked-in bookings (d7fcf32)
  • api.py: add filtering by day of week and start time for class retrieval (96d20e0)
  • api.py: add home_studio_uuid parameter to Otf class for better user context management (f03b6a5)
  • api.py: add hydrate method to Otf class to create instances from a dictionary (8577ad1)
  • api.py: add logging and print statement when starting background token refresh task (12b6f9f)
  • api.py: add main function to initialize Otf instance using env vars (c1d9315)
  • api.py: add methods to get booking by class and booking UUID for better booking management (6094072)
  • api.py: add new exceptions for booking errors to improve error handling (6094072)
  • api.py: add optional device_key parameter to hydrate method to allow more flexible instantiation (c5e2560)
  • api.py: add print statement to debug background task for refreshing token (a8f04ac)
  • api.py: add retry logic to _get_performance_summary_raw to handle intermittent None responses (82e9fb0)
  • api.py: add support for refresh_token and device_key in Otf class initialization (04c4294)
  • api.py: add support for token-based authentication and background token refresh (554e968)
  • api.py: add support for user object and refresh callback in Otf class (a081fe2)
  • api.py: add user parameter to Otf class constructor to allow passing a user object (7508b09)
  • api.py: enhance class booking and cancellation with additional checks and error handling (6094072)
  • api.py: extend Api.create method to support token-based authentication (85185eb)
  • api: add class and coach rating functionality (1032df1)
  • api: implement async context manager methods in Otf class to automatically handle session lifecycle (ed4f287)
  • api: implement get_studios_by_geo as alias for search_studios_by_geo (ed4f287)
  • auth.py, user.py: add has_cached_credentials method to check for cached credentials (ed4f287)
  • auth.py: add check_token method to verify and optionally renew access tokens (30faeb6)
  • auth.py: add class methods for creating OtfCognito instances from tokens and login credentials (80a64ac)
  • auth.py: add device key support to OtfCognito class for enhanced security (a938c06)
  • auth.py: add koji_person_id field to IdClaimsData model to include custom identifier (0c1b489)
  • auth.py: add logging for token refresh to improve debugging and monitoring (1192201)
  • auth.py: add logging to track token refresh process (63c2199)
  • auth.py: add logging when clearing device key to improve traceability (101f195)
  • auth.py: add method to create User instance from an id token (554e968)
  • auth.py: add methods to check and retrieve username from cache file (4647b55)
  • auth.py: add model_config to OtfUser to allow arbitrary types in pydantic model (11d3869)
  • auth.py: add OtfCognito class to handle device metadata and token renewal (9e9de81)
  • auth.py: add property and setter for device_key with logging for security (1538fec)
  • auth.py: add validation for refresh_callback to ensure it is a callable function with one argument (15a4dd4)
  • auth: add get_tokens method to OtfUser class to retrieve tokens (c520e39)
  • base.py: add item getter methods to OtfBaseModel for flexible key access (0282e67)
  • bookings.py: add book and cancel commands to manage class bookings (b0f9f70)
  • bookings.py: add BookingStatusCli enum for CLI-friendly booking statuses (0282e67)
  • bookings.py: add interactive booking cancellation feature to improve user experience (5095e6b)
  • bookings.py: add interactive booking options for studio UUIDs, date range, class type, day of week, and start time (96d20e0)
  • bookings.py: integrate OtfClassTimeMixin into OtfClass for time-related properties (0282e67)
  • bookings.py: update BookingList to include new class time columns (0282e67)
  • bookings: add methods to BookingStatus and StudioStatus enums for case-insensitive lookups and listing all statuses (4647b55)
  • bookings: add to_table method to BookingList for rich table representation (4647b55)
  • cancel_booking: add new response model for cancel booking (195e4da)
  • classes_api: add class_type and exclude_cancelled filters to get_classes method (ffc1cee)
  • classes_api: add filtering by date range and limit to get_classes method (76a358a)
  • classes_api: integrate booking status to mark classes as booked (ffc1cee)
  • classes.py: add ClassType and ClassTypeCli enums for class type management (0282e67)
  • classes.py: add DoW enum for day of week filtering and case-insensitive matching (96d20e0)
  • classes.py: add OtfClassTimeMixin for time-related properties in OtfClass (0282e67)
  • classes.py: enhance OtfClass with sidebar data and availability properties (0282e67)
  • classes.py: update OtfClassList to include new class time columns (0282e67)
  • classes: add class_name to sidebar_data in OtfClass (0c1b489)
  • classes: add table representation for class list (195e4da)
  • cli: add bookings command to list booking data (3bf547b)
  • cli: add classes command to CLI for listing classes (76a358a)
  • cli: add exclude_cancelled option to list_bookings command (b1de127)
  • cli: add interactive booking command to book classes interactively (b1de127)
  • cli: add prompts module for user input and selection (b1de127)
  • cli: add utility functions for CLI exception handling and async support (3bf547b)
  • cli: implement CLI structure with AsyncTyper and command handling (3bf547b)
  • deps: add httpx version 0.27.0 for HTTP requests (b7f8f91)
  • examples: add class bookings example script to demonstrate API usage (292c987)
  • examples: add favorite studio management to studio_examples.py (ed4f287)
  • exceptions.py: add original_exception attribute to OtfRequestError for better error context (e3cb63a)
  • exceptions.py: introduce ConflictingBookingError to handle booking conflicts (ed4f287)
  • filters.py: add filter_classes method to ClassFilter to encapsulate filtering logic and enhance reusability (ed4f287)
  • lifetime_stats.py: add new model for lifetime statistics response (0c1b489)
  • member_api.py: add book_class and cancel_booking methods to handle booking operations (b0f9f70)
  • member_api: add exclude_cancelled parameter to filter out cancelled bookings (60366bc)
  • member_detail.py: add MemberReferrer class to handle member referrer data (1f8e2d2)
  • models: add _columns method to BookingList for table headers (0c1b489)
  • models: add attr_to_column_header method to OtfClass and Booking classes for dynamic column header mapping (2376c94)
  • models: add BetterDumperMixin for enhanced Pydantic model dumping (812bf72)
  • models: add BodyCompositionData model to handle body composition responses (0c1b489)
  • models: add book_class response models to handle booking data (195e4da)
  • models: add BookClass and CancelBooking to response models (195e4da)
  • models: add new Pydantic models for handling booking and client data (195e4da)
  • models: add properties to Booking for id_val and sidebar_data (0c1b489)
  • models: add Telemetry model to handle telemetry data (63feb5f)
  • models: start updating models to handle missing data, exclude data, remove unnecessary sub models (d671bc2)
  • otf_api: introduce OtfSync class for synchronous API interactions (ed4f287)
  • pyproject.toml: add CLI script entry point for otf_api (3bf547b)
  • pyproject.toml: add new development dependencies for testing and code quality (b55df47)
  • pyproject.toml: add pint library to dependencies for unit conversion functionality (2569dbc)
  • pyproject.toml: add python-box and inflection dependencies to enhance functionality (06c2980)
  • pyproject.toml: add readchar and humanize dependencies for enhanced CLI functionality (dd6ab5b)
  • pyproject.toml: add typer and pendulum dependencies for CLI support (06a11d6)
  • pyproject.toml: update aiohttp from 3.8.6 to 3.10.5 to work with Python 3.11+ (fed9073)
  • python_package.yml: add create-release job to automate GitHub release creation after publishing to PyPI (2b481b6)
  • tox.ini: add pipx install poetry in commands_pre to ensure poetry is installed (eefb5b3)
  • utils.py: enable environment variable support for username and password to facilitate automated authentication (ed4f287)

Bug Fixes

  • api.py: add **kwargs to API request methods to allow additional parameters (308e9c5)
  • api.py: add check for session attribute before attempting to close it (84faff4)
  • api.py: add hasattr check for _refresh_task in shutdown method to prevent attribute error (264fc8a)
  • api.py: add synchronous member details retrieval to avoid async initialization issues (04c4294)
  • api.py: allow multiple class types for class retrieval (96d20e0)
  • api.py: change User method from load_from_disk to login for clarity (84faff4)
  • api.py: clear cache after rating a class to ensure updated data is returned (2fb5b3c)
  • api.py: deprecate limit argument in get_performance_summaries to simplify API (2fb5b3c)
  • api.py: enhance error message to include provided authentication kwargs (ecae909)
  • api.py: ensure distance does not exceed 250 miles in _get_studios_by_geo to adhere to API constraints (ed4f287)
  • api.py: improve error handling by logging response text on exceptions (308e9c5)
  • api.py: initialize _ref attribute to None to avoid potential attribute errors (82baf91)
  • api.py: initialize aiohttp.ClientSession with authorization headers to ensure authenticated requests (d7fcf32)
  • api.py: update type hints and docstrings for consistency and clarity (2fb5b3c)
  • api.py: wrap signal handling in try-except block to prevent crashes on unsupported platforms (b55df47)
  • api: correct page size limit in search_studios_by_geo to 100 (ed4f287)
  • api: update telemetry method to use performance_summary_id instead of class_history_uuid (a1ce303)
  • auth.py: add check for existing device key before clearing to avoid unnecessary log entries (e131c66)
  • auth.py: add token verification to ensure tokens are valid before creating User instance (0690fef)
  • auth.py: add type annotations and return types to check_token method for better clarity and type safety (80a64ac)
  • auth.py: change log level from debug to info for token refresh message (a8f04ac)
  • auth.py: change refresh_token method to return a boolean indicating success (a081fe2)
  • auth.py: correct attribute name from device_metadata to device_key for token generation (2f9bc99)
  • auth.py: ensure refresh callback is called after token refresh (e4dacc2)
  • auth.py: ensure token properties return values from cognito if available (ed4f287)
  • auth.py: handle TokenVerificationException during access token renewal (a938c06)
  • auth.py: move background refresh task to OtfUser class to ensure token refresh logic is encapsulated within the user class (15a4dd4)
  • auth.py: move token refresh log message to correct location and ensure save_to_disk is called only when tokens are refreshed (f23865e)
  • auth.py: remove optional parameters from load_from_disk method to ensure username and password are always provided for reauthentication (907f626)
  • auth.py: remove redundant hasattr check before clearing device key (764a715)
  • auth.py: update device_key property to handle None type values (2503728)
  • auth: update type hints from Cognito to OtfCognito for consistency (ed4f287)
  • body_composition_list.py: remove empty line to make linter happy (26f1a47)
  • body_composition_list.py: update member_id type to accept both str and int (ed4f287)
  • bookings.py: make description field optional in Studio model to handle cases where description might be missing (bba0d5e)
  • classes_api: correct variable name from res to classes_resp for clarity (ffc1cee)
  • classes.py: remove usage of Self type hint for compatibility with older Python versions (d08c643)
  • classes.py: return DoW instead of string from day_of_week_enum (194f1ff)
  • classes: change "90 min" to "90 minutes" for consistency (0c1b489)
  • cli: add help descriptions for book and cancel options (ce2bccc)
  • cli: add missing envvar for OPT_OUTPUT option in app.py (ce2bccc)
  • cli: correct columns method calls in bookings and classes (ce2bccc)
  • cliff.toml: add default value for commit_id to handle undefined cases (ab5cbdc)
  • cliff.toml: ensure commit_id is present before adding unreleased (9d2cca5)
  • cli: remove unused kwargs in list_bookings and list_classes (ce2bccc)
  • cli: update command aliases to name in bookings and classes (ce2bccc)
  • correct import paths for User and Otf classes (0ffb313)
  • dependencies: change aiohttp version to 3.8.* for better compatibility (9845822)
  • enums.py: change EquipmentType and ChallengeType to use IntEnum for better integer handling (ed4f287)
  • examples: correct instantiation of Otf class in examples to remove async creation method (3adcd6c)
  • exceptions: add specific exceptions for rating errors (1032df1)
  • fix the thing i just broke, use .parent (7c44ac8)
  • gen_ref_pages.py: skip files named version in documentation generation (4332db8)
  • imports: update all references to User to OtfUser to match new class name (c520e39)
  • mask strictness passes through non-PII primitive and structural values (#112) (b57c93b)
  • member_api: update sorting key to use starts_at_local instead of start_date_time (60366bc)
  • member_detail.py: allow for no homePhone (7568833)
  • member_detail.py: correct member_address_uuid field to handle None values and unify alias handling (0c1b489)
  • mixins: make address_line1 optional in AddressMixin for flexibility (ed4f287)
  • models/base.py: change model_config extra from "forbid" to "allow" to permit additional fields (2c96d37)
  • models: exclude sensitive fields from API responses for better security and privacy (4647b55)
  • models: make created_by and updated_by fields optional (0c1b489)
  • models: update init.py to include missing imports and reorder (c1d9315)
  • models: update imports and all to reflect Telemetry changes (63feb5f)
  • pass the correct object to models to use in api calls (80ac6ef)
  • performance_summary_detail.py: exclude and hide ratable field due to inaccuracy in reflecting data from PerformanceSummaryEntry (e48b8b5)
  • performance_summary_list.py: add type field to Class model (02d9a08)
  • prompts.py: handle empty data list in prompt_select_from_table function (812bf72)
  • prompts.py: highlight already booked classes in grey in selection table (96d20e0)
  • pyproject.toml: correct typo in pytest configuration section header (062eb3d)
  • pyproject.toml: pin griffe < 1 to fix mkdocs build (06ad79d)
  • pyproject.toml: reorder dependencies alphabetically for better readability (b55df47)
  • responses: update init.py to include missing imports and reorder (c1d9315)
  • telemetry.py: add rowData fields to Telemetry model (74e72f4)
  • telemetry.py: allow for no hr data in telemetry (823d57b)
  • telemetry.py: lowercase row_spm (d54beb4)
  • tox.ini: add poetry install command to ensure dev dependencies are installed before running checks (3f6957f)
  • tox.ini: replace poetry with pipx in deps to manage dependencies (eefb5b3)
  • update CLIENT_ID value from newest apk (f9f3495)
  • use correct attribute for cache directory (eb1356b)
  • use correct attribute for cache directory (89f5f87)
  • workout_examples.py: remove duplicate assignment of otf variable to prevent redundancy (1f8e2d2)

Performance Improvements

  • api.py: cache _get_performance_summary_raw to improve performance by reducing redundant API calls (82e9fb0)
  • api.py: use ThreadPoolExecutor for concurrent fetching of studio and performance summary details (2fb5b3c)

Documentation

  • api.py, auth.py: simplify and clarify the description of refresh_callback parameter in docstrings (afe8959)
  • api.py: add docstring to Api.create method to describe new parameters and return type (85185eb)
  • api.py: update docstrings to include home_studio_uuid parameter and new methods (f03b6a5)
  • auth_examples: remove outdated comments related to cache_device_data option (ed4f287)
  • auth.py: update docstrings to reflect changes in token handling and device key usage (a938c06)
  • auth: update all to reflect the renamed OtfUser class (c520e39)
  • CONTRIBUTING.md: update reference from HISTORY.md to CHANGELOG.md (d6ca531)
  • examples: add example for rating a class (1032df1)
  • examples: update workout examples to reflect new API methods (ed4f287)
  • index.md: fix include-markdown path to correctly reference usage.md (d456660)
  • index.md: replace README.md include with detailed API client description and installation instructions (082e065)
  • mkdocs.yml: rename 'History' to 'Changelog' for clarity (435da88)
  • mkdocs.yml: update email contact (435da88)
  • pyproject.toml: add documentation URL to project metadata (062eb3d)
  • README.md, pyproject.toml: update documentation link to stable version (0139146)
  • README.md, usage.md: update class name from Api to Otf for accuracy (3adcd6c)
  • README.md: expand documentation with installation, usage, and examples (603df75)
  • README.md: remove extra blank line before disclaimer (c52a8dd)
  • README.md: remove extra blank line before disclaimer (082e065)
  • README.md: remove outdated information about future goals for API methods (4b82b38)
  • README.md: replace usage include with overview section and exam… (de16962)
  • README.md: replace usage include with overview section and examples link to provide better guidance on using the API (2d9390d)
  • remove installation guide from documentation and mkdocs navigation (0139146)
  • rename history.md to changelog.md and update references (d6ca531)
  • update example scripts to use Otf class instead of Api (0ffb313)
  • workflows: correct typos in package download URLs in dev and release workflows (a60c055)

Code Refactoring

  • codebase audit fixes — bugs, legacy removal, model cleanup (#115) (f5d587f)