otf-api 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- otf_api/__version__.py +1 -1
- otf_api-0.2.2.dist-info/METADATA +284 -0
- {otf_api-0.2.0.dist-info → otf_api-0.2.2.dist-info}/RECORD +6 -6
- otf_api-0.2.0.dist-info/METADATA +0 -28
- {otf_api-0.2.0.dist-info → otf_api-0.2.2.dist-info}/AUTHORS.md +0 -0
- {otf_api-0.2.0.dist-info → otf_api-0.2.2.dist-info}/LICENSE +0 -0
- {otf_api-0.2.0.dist-info → otf_api-0.2.2.dist-info}/WHEEL +0 -0
otf_api/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.2.
|
1
|
+
__version__ = "0.2.2"
|
@@ -0,0 +1,284 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: otf-api
|
3
|
+
Version: 0.2.2
|
4
|
+
Summary: Python OrangeTheory Fitness API Client
|
5
|
+
License: MIT
|
6
|
+
Author: Jessica Smith
|
7
|
+
Author-email: j.smith.git1@gmail.com
|
8
|
+
Requires-Python: >=3.10,<4.0
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
10
|
+
Classifier: Intended Audience :: Developers
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
12
|
+
Classifier: Operating System :: OS Independent
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
17
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
21
|
+
Requires-Dist: aiohttp (==3.9.5)
|
22
|
+
Requires-Dist: loguru (==0.7.2)
|
23
|
+
Requires-Dist: pycognito (==2024.5.1)
|
24
|
+
Requires-Dist: pydantic (==2.7.3)
|
25
|
+
Project-URL: Documentation, https://otf-api.readthedocs.io/en/stable/
|
26
|
+
Description-Content-Type: text/markdown
|
27
|
+
|
28
|
+
Simple API client for interacting with the OrangeTheory Fitness APIs.
|
29
|
+
|
30
|
+
|
31
|
+
This library allows access to the OrangeTheory API to retrieve workouts and performance data, class schedules, studio information, and bookings. It is a work in progress, currently only allowing access to GET calls, but my goal is to expand it to include POST, PUT, and DELETE calls as well.
|
32
|
+
|
33
|
+
## Installation
|
34
|
+
```bash
|
35
|
+
pip install otf-api
|
36
|
+
```
|
37
|
+
|
38
|
+
## Overview
|
39
|
+
|
40
|
+
To use the API, you need to create an instance of the `Api` class, providing your email address and password. This will authenticate you with the API and allow you to make requests. When the `Api` object is created it automatically grabs your member details and home studio, to simplify the process of making requests.
|
41
|
+
|
42
|
+
The `Api` object has multiple api objects as attributes, which you can use to make requests to the API. The available api objects are:
|
43
|
+
|
44
|
+
- `classes_api`
|
45
|
+
- `members_api`
|
46
|
+
- `performance_api`
|
47
|
+
- `studios_api`
|
48
|
+
- `telemetry_api`
|
49
|
+
|
50
|
+
|
51
|
+
## Example Usage
|
52
|
+
|
53
|
+
Note: see more examples in the `examples` directory and in the [usage docs](https://otf-api.readthedocs.io/en/stable/usage/).
|
54
|
+
|
55
|
+
```python
|
56
|
+
import asyncio
|
57
|
+
import json
|
58
|
+
import os
|
59
|
+
|
60
|
+
from otf_api import Api
|
61
|
+
|
62
|
+
USERNAME = os.getenv("OTF_EMAIL")
|
63
|
+
PASSWORD = os.getenv("OTF_PASSWORD")
|
64
|
+
|
65
|
+
|
66
|
+
async def main():
|
67
|
+
otf = await Api.create(USERNAME, PASSWORD)
|
68
|
+
|
69
|
+
# performance summaries are historical records of your performance in workouts
|
70
|
+
# `get_performance_summaries` takes a limit (default of 30) and returns a list of summaries
|
71
|
+
data_list = await otf.performance_api.get_performance_summaries()
|
72
|
+
print(json.dumps(data_list.summaries[0].model_dump(), indent=4, default=str))
|
73
|
+
"""
|
74
|
+
{
|
75
|
+
"performance_summary_id": "29dd97f4-3418-4247-b35c-37eabc5e17f3",
|
76
|
+
"details": {
|
77
|
+
"calories_burned": 506,
|
78
|
+
"splat_points": 18,
|
79
|
+
"step_count": 0,
|
80
|
+
"active_time_seconds": 3413,
|
81
|
+
"zone_time_minutes": {
|
82
|
+
"gray": 2,
|
83
|
+
"blue": 13,
|
84
|
+
"green": 24,
|
85
|
+
"orange": 16,
|
86
|
+
"red": 2
|
87
|
+
}
|
88
|
+
},
|
89
|
+
"ratable": true,
|
90
|
+
"class_": {
|
91
|
+
"ot_base_class_uuid": "b6549fc2-a479-4b03-9303-e0e45dbcd8c9",
|
92
|
+
"starts_at_local": "2024-06-11T09:45:00",
|
93
|
+
"name": "Orange 60 Min 2G",
|
94
|
+
"coach": ...,
|
95
|
+
"studio": ...,
|
96
|
+
},
|
97
|
+
"ratings": null
|
98
|
+
}
|
99
|
+
"""
|
100
|
+
|
101
|
+
# you can get detailed information about a specific performance summary by calling `get_performance_summary`
|
102
|
+
# which takes a performance_summary_id as an argument
|
103
|
+
data = await otf.performance_api.get_performance_summary(data_list.summaries[0].performance_summary_id)
|
104
|
+
print(json.dumps(data.model_dump(), indent=4, default=str))
|
105
|
+
|
106
|
+
"""
|
107
|
+
{
|
108
|
+
"id": "29dd97f4-3418-4247-b35c-37eabc5e17f3",
|
109
|
+
"details": {
|
110
|
+
"calories_burned": 506,
|
111
|
+
"splat_points": 18,
|
112
|
+
"step_count": 3314,
|
113
|
+
"active_time_seconds": 0,
|
114
|
+
"zone_time_minutes": {
|
115
|
+
"gray": 2,
|
116
|
+
"blue": 13,
|
117
|
+
"green": 24,
|
118
|
+
"orange": 16,
|
119
|
+
"red": 2
|
120
|
+
},
|
121
|
+
"heart_rate": {
|
122
|
+
"max_hr": 0,
|
123
|
+
"peak_hr": 180,
|
124
|
+
"peak_hr_percent": 94,
|
125
|
+
"avg_hr": 149,
|
126
|
+
"avg_hr_percent": 78
|
127
|
+
},
|
128
|
+
"equipment_data": {
|
129
|
+
"treadmill": {
|
130
|
+
"avg_pace": {
|
131
|
+
"display_value": "15:23",
|
132
|
+
"display_unit": "min/mile",
|
133
|
+
"metric_value": "923"
|
134
|
+
},
|
135
|
+
"avg_speed": {
|
136
|
+
"display_value": 3.9,
|
137
|
+
"display_unit": "mph",
|
138
|
+
"metric_value": 3.9
|
139
|
+
},
|
140
|
+
"max_pace": ...,
|
141
|
+
"max_speed": ...,
|
142
|
+
"moving_time": ...,
|
143
|
+
"total_distance": ...,
|
144
|
+
"avg_incline": ...,
|
145
|
+
"elevation_gained": ...,
|
146
|
+
"max_incline": ...
|
147
|
+
},
|
148
|
+
"rower": ...
|
149
|
+
}
|
150
|
+
},
|
151
|
+
"ratable": false,
|
152
|
+
"class_": {
|
153
|
+
"starts_at_local": "2024-06-11T09:45:00",
|
154
|
+
"name": "Orange 60 Min 2G"
|
155
|
+
}
|
156
|
+
}
|
157
|
+
"""
|
158
|
+
|
159
|
+
# workouts is a similar endpoint but returns more data - this is what OTLive uses to display workout history
|
160
|
+
# this endpoint takes no arguments and returns all workouts back to, as far as we can tell, around 2019
|
161
|
+
workouts = await otf.member_api.get_workouts()
|
162
|
+
print(json.dumps(workouts.workouts[0].model_dump(), indent=4, default=str))
|
163
|
+
"""
|
164
|
+
{
|
165
|
+
"studio_number": "8292",
|
166
|
+
"studio_name": "AnyTown OH - East",
|
167
|
+
"class_type": "Orange 60 Min 2G",
|
168
|
+
"active_time": 3413,
|
169
|
+
"coach": "Coach",
|
170
|
+
"member_uuid": "b4df31a6-fa54-4a7f-85eb-1f5b613c6414",
|
171
|
+
"class_date": "2024-06-11 09:45:00+00:00",
|
172
|
+
"total_calories": 506,
|
173
|
+
"avg_hr": 149,
|
174
|
+
"max_hr": 180,
|
175
|
+
"avg_percent_hr": 78,
|
176
|
+
"max_percent_hr": 94,
|
177
|
+
"total_splat_points": 18,
|
178
|
+
"red_zone_time_second": 137,
|
179
|
+
"orange_zone_time_second": 979,
|
180
|
+
"green_zone_time_second": 1415,
|
181
|
+
"blue_zone_time_second": 769,
|
182
|
+
"black_zone_time_second": 113,
|
183
|
+
"step_count": 3314,
|
184
|
+
"class_history_uuid": "c71658c3-46e7-410b-8ffa-9a8ffd3828fa",
|
185
|
+
"class_id": "30299",
|
186
|
+
"date_created": "2024-06-11 10:43:00+00:00",
|
187
|
+
"date_updated": "2024-06-11 10:43:00+00:00",
|
188
|
+
"is_intro": false,
|
189
|
+
"is_leader": false,
|
190
|
+
"member_email": null,
|
191
|
+
"member_name": "Member Name",
|
192
|
+
"member_performance_id": "0cbc39d3-bb9b-4021-8006-8eb23c272f0d",
|
193
|
+
"minute_by_minute_hr": [
|
194
|
+
108,
|
195
|
+
147,
|
196
|
+
149,
|
197
|
+
...
|
198
|
+
],
|
199
|
+
"source": "OTbeat Live",
|
200
|
+
"studio_account_uuid": "studio-number-0325",
|
201
|
+
"version": "1",
|
202
|
+
"workout_type": {
|
203
|
+
"id": 101,
|
204
|
+
"display_name": "Studio Workout",
|
205
|
+
"icon": ""
|
206
|
+
}
|
207
|
+
}
|
208
|
+
"""
|
209
|
+
|
210
|
+
# telemetry is a detailed record of a specific workout - minute by minute, or more granular if desired
|
211
|
+
# this endpoint takes a class_history_uuid, as well as a number of max data points - if you do not pass
|
212
|
+
# this value it will attempt to return enough data points for 30 second intervals
|
213
|
+
telemetry = await otf.telemetry_api.get_telemetry(workouts.workouts[0].class_history_uuid)
|
214
|
+
print(json.dumps(telemetry.model_dump(), indent=4, default=str))
|
215
|
+
|
216
|
+
"""
|
217
|
+
{
|
218
|
+
"member_uuid": "fa323d40-bfae-4e72-872c-e11188d182a7",
|
219
|
+
"class_history_uuid": "5945a723-930b-449a-bd8f-8267a4ff392f",
|
220
|
+
"class_start_time": "2024-06-11 14:46:07+00:00",
|
221
|
+
"max_hr": 191,
|
222
|
+
"zones": {
|
223
|
+
"gray": {
|
224
|
+
"start_bpm": 96,
|
225
|
+
"end_bpm": 116
|
226
|
+
},
|
227
|
+
"blue": {
|
228
|
+
"start_bpm": 117,
|
229
|
+
"end_bpm": 135
|
230
|
+
},
|
231
|
+
"green": {
|
232
|
+
"start_bpm": 136,
|
233
|
+
"end_bpm": 159
|
234
|
+
},
|
235
|
+
"orange": {
|
236
|
+
"start_bpm": 160,
|
237
|
+
"end_bpm": 175
|
238
|
+
},
|
239
|
+
"red": {
|
240
|
+
"start_bpm": 176,
|
241
|
+
"end_bpm": 191
|
242
|
+
}
|
243
|
+
},
|
244
|
+
"window_size": 30,
|
245
|
+
"telemetry": [
|
246
|
+
{
|
247
|
+
"relative_timestamp": 0,
|
248
|
+
"hr": 105,
|
249
|
+
"agg_splats": 0,
|
250
|
+
"agg_calories": 2,
|
251
|
+
"timestamp": "2024-06-11 14:46:07+00:00",
|
252
|
+
"tread_data": {
|
253
|
+
"tread_speed": 1.34,
|
254
|
+
"tread_incline": 1.0,
|
255
|
+
"agg_tread_distance": 9
|
256
|
+
}
|
257
|
+
},
|
258
|
+
{
|
259
|
+
"relative_timestamp": 30,
|
260
|
+
"hr": 132,
|
261
|
+
"agg_splats": 0,
|
262
|
+
"agg_calories": 4,
|
263
|
+
"timestamp": "2024-06-11 14:46:37+00:00",
|
264
|
+
"tread_data": {
|
265
|
+
"tread_speed": 2.46,
|
266
|
+
"tread_incline": 1.0,
|
267
|
+
"agg_tread_distance": 62
|
268
|
+
}
|
269
|
+
},
|
270
|
+
...
|
271
|
+
]
|
272
|
+
}
|
273
|
+
"""
|
274
|
+
|
275
|
+
|
276
|
+
if __name__ == "__main__":
|
277
|
+
asyncio.run(main())
|
278
|
+
|
279
|
+
```
|
280
|
+
|
281
|
+
|
282
|
+
Disclaimer:
|
283
|
+
This project is in no way affiliated with OrangeTheory Fitness.
|
284
|
+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
otf_api/__init__.py,sha256=FkZ1Yc26-CSBaRr1aPCOxjAg-QGkDzMalj-7tBHi7MA,1580
|
2
|
-
otf_api/__version__.py,sha256=
|
2
|
+
otf_api/__version__.py,sha256=m6kyaNpwBcP1XYcqrelX2oS3PJuOnElOcRdBa9pEb8c,22
|
3
3
|
otf_api/api.py,sha256=Ua8rTeJUdX-gP_TJJteWB7axTef-9LSEDvy8Pahg6C0,5023
|
4
4
|
otf_api/classes_api.py,sha256=KaKYM32rUa9Ofd6AV4hNF7YF3EWuQa1S40bWhYg06PQ,1594
|
5
5
|
otf_api/member_api.py,sha256=UamXcW0w-gbmVOWfJLQoNJYermwNAX_aL8AIZvwAAa8,15146
|
@@ -31,8 +31,8 @@ otf_api/performance_api.py,sha256=vQpziBdMkN4MsdF6--uqr9fjbf-tQIezNvXtBv-CeWU,20
|
|
31
31
|
otf_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
32
|
otf_api/studios_api.py,sha256=7h6ZMJS9bWCVdpnSlVY4neLYiIagVKPzZSrxi1fB8-U,3568
|
33
33
|
otf_api/telemetry_api.py,sha256=LvtBlbXZfxUNhX_dcvCt01DgLJ7DZrUcsWF0VvcT0AE,3715
|
34
|
-
otf_api-0.2.
|
35
|
-
otf_api-0.2.
|
36
|
-
otf_api-0.2.
|
37
|
-
otf_api-0.2.
|
38
|
-
otf_api-0.2.
|
34
|
+
otf_api-0.2.2.dist-info/AUTHORS.md,sha256=FcNWMxpe8KDuTq4Qau0SUXsabQwGs9TGnMp1WkXRnj8,123
|
35
|
+
otf_api-0.2.2.dist-info/LICENSE,sha256=UaPT9ynYigC3nX8n22_rC37n-qmTRKLFaHrtUwF9ktE,1071
|
36
|
+
otf_api-0.2.2.dist-info/METADATA,sha256=GSmOVcyrS3IhOrSWAVPipp8zTERIeGVgmmqmhMSt7lU,9532
|
37
|
+
otf_api-0.2.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
38
|
+
otf_api-0.2.2.dist-info/RECORD,,
|
otf_api-0.2.0.dist-info/METADATA
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: otf-api
|
3
|
-
Version: 0.2.0
|
4
|
-
Summary: Python OrangeTheory Fitness API Client
|
5
|
-
License: MIT
|
6
|
-
Author: Jessica Smith
|
7
|
-
Author-email: j.smith.git1@gmail.com
|
8
|
-
Requires-Python: >=3.10,<4.0
|
9
|
-
Classifier: Development Status :: 4 - Beta
|
10
|
-
Classifier: Intended Audience :: Developers
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Classifier: Operating System :: OS Independent
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
17
|
-
Classifier: Topic :: Internet :: WWW/HTTP
|
18
|
-
Classifier: Topic :: Software Development :: Libraries
|
19
|
-
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
21
|
-
Requires-Dist: aiohttp (==3.9.5)
|
22
|
-
Requires-Dist: loguru (==0.7.2)
|
23
|
-
Requires-Dist: pycognito (==2024.5.1)
|
24
|
-
Requires-Dist: pydantic (==2.7.3)
|
25
|
-
Description-Content-Type: text/markdown
|
26
|
-
|
27
|
-
Simple API client for interacting with the OrangeTheory APIs. This project is in now way affiliated with OrangeTheory Fitness.
|
28
|
-
|
File without changes
|
File without changes
|
File without changes
|