A Python wrapper for the WHOOP API
Project description
whoop-client
A Python wrapper for the WHOOP API.
Provides both synchronous and asynchronous clients with Pydantic models, automatic retries, OAuth2 token management, and an MCP server for AI assistants.
Installation
pip install whoop-client
Requires Python 3.10+.
Quick Start
With an access token
from whoop_client import WhoopClient
with WhoopClient("your-access-token") as client:
profile = client.get_profile()
print(f"Hello, {profile.first_name}!")
for cycle in client.iter_cycles():
if cycle.score:
print(f"Strain: {cycle.score.strain}")
Async
import asyncio
from whoop_client import AsyncWhoopClient
async def main():
async with AsyncWhoopClient("your-access-token") as client:
profile = await client.get_profile()
print(f"Hello, {profile.first_name}!")
async for cycle in client.iter_cycles():
if cycle.score:
print(f"Strain: {cycle.score.strain}")
asyncio.run(main())
With OAuth2 token refresh
from whoop_client import WhoopClient, OAuthTokenProvider
token_provider = OAuthTokenProvider(
client_id="your-client-id",
client_secret="your-client-secret",
refresh_token="your-refresh-token",
)
with WhoopClient(token_provider) as client:
profile = client.get_profile()
The OAuthTokenProvider automatically refreshes expired tokens. An AsyncOAuthTokenProvider is available for the async client.
API
Clients
Both WhoopClient and AsyncWhoopClient accept the same constructor arguments:
WhoopClient(
token_provider, # Access token string or TokenProvider instance
*,
base_url="...", # Override API base URL
timeout=30.0, # Request timeout in seconds
retry_policy=None, # Custom RetryPolicy, or None for defaults
httpx_client=None, # Bring your own httpx.Client
)
Endpoints
| Method | Description |
|---|---|
get_cycles(...) |
List cycles (paginated) |
get_cycle_by_id(id) |
Get a single cycle |
get_cycle_sleep(id) |
Get sleep for a cycle |
get_cycle_recovery(id) |
Get recovery for a cycle |
get_recoveries(...) |
List recoveries (paginated) |
get_sleeps(...) |
List sleeps (paginated) |
get_sleep_by_id(id) |
Get a single sleep |
get_workouts(...) |
List workouts (paginated) |
get_workout_by_id(id) |
Get a single workout |
get_profile() |
Get basic user profile |
get_body_measurement() |
Get body measurements |
revoke_access() |
Revoke the OAuth access token |
get_activity_mapping(v1_id) |
Map a V1 activity ID to V2 |
Paginated endpoints accept limit, start, end, and next_token parameters. They return a PaginatedResponse[T] with records and next_token fields.
Auto-Pagination
Use the iter_* methods to automatically paginate through all results:
iter_cycles(...)iter_recoveries(...)iter_sleeps(...)iter_workouts(...)
These return Iterator[T] (sync) or AsyncIterator[T] (async).
Retry Policy
Requests are retried automatically on transient failures (429, 5xx, timeouts, connection errors) with exponential backoff and jitter. Customize with RetryPolicy:
from whoop_client import WhoopClient, RetryPolicy
policy = RetryPolicy(
max_retries=5,
backoff_factor=1.0,
max_backoff_seconds=120.0,
)
client = WhoopClient("token", retry_policy=policy)
Exceptions
All exceptions inherit from WhoopError:
| Exception | Trigger |
|---|---|
WhoopBadRequestError |
400 response |
WhoopAuthenticationError |
401 response |
WhoopNotFoundError |
404 response |
WhoopRateLimitError |
429 response (has retry_after attribute) |
WhoopServerError |
5xx response |
WhoopConnectionError |
Network failure |
WhoopTimeoutError |
Request timeout |
WhoopAuthTokenError |
Token refresh failure |
API errors carry status_code and response attributes for full introspection.
Obtaining Tokens (whoop-client auth)
The whoop-client auth command runs the OAuth2 Authorization Code flow to obtain access and refresh tokens from WHOOP.
Prerequisites
Set your OAuth2 credentials as environment variables (or pass them as flags):
export WHOOP_CLIENT_ID="your-client-id"
export WHOOP_CLIENT_SECRET="your-client-secret"
Usage
whoop-client auth
This opens your browser, waits for the OAuth2 callback, and saves the tokens to ~/.config/whoop-client/tokens.json.
Options
| Flag | Description | Default |
|---|---|---|
--client-id |
OAuth2 client ID | $WHOOP_CLIENT_ID |
--client-secret |
OAuth2 client secret | $WHOOP_CLIENT_SECRET |
--scopes |
OAuth2 scopes to request | All read scopes |
--port |
Local callback server port | 8080 |
--redirect-uri |
OAuth2 redirect URI | http://localhost:8080/callback |
--token-file |
Output file path | ~/.config/whoop-client/tokens.json |
--no-open |
Print the URL instead of opening the browser | — |
Example
# Use env vars, save to custom file
whoop-client auth --token-file my-tokens.json
# Pass credentials directly
whoop-client auth --client-id ID --client-secret SECRET
# Headless (e.g. SSH session) — prints the URL to visit manually
whoop-client auth --no-open
MCP Server
whoop-client includes an MCP server that exposes WHOOP data as tools for AI assistants like Claude.
Installation
pip install "whoop-client[mcp]"
Configuration
The server requires WHOOP API credentials via environment variables:
Option 1: OAuth2 with auto-refresh (recommended)
| Variable | Description |
|---|---|
WHOOP_CLIENT_ID |
OAuth2 client ID |
WHOOP_CLIENT_SECRET |
OAuth2 client secret |
WHOOP_REFRESH_TOKEN |
OAuth2 refresh token |
WHOOP_ACCESS_TOKEN |
(Optional) Initial access token to avoid an initial refresh |
Option 2: Static access token
| Variable | Description |
|---|---|
WHOOP_ACCESS_TOKEN |
A valid WHOOP API access token |
Usage
Run the server directly:
whoop-client mcp
Available Tools
| Tool | Description |
|---|---|
get_cycles |
List physiological cycles (paginated) |
get_cycle_by_id |
Get a single cycle |
get_cycle_sleep |
Get sleep for a cycle |
get_cycle_recovery |
Get recovery for a cycle |
get_recoveries |
List recovery records (paginated) |
get_sleeps |
List sleep records (paginated) |
get_sleep_by_id |
Get a single sleep record |
get_workouts |
List workout records (paginated) |
get_workout_by_id |
Get a single workout record |
get_profile |
Get basic user profile |
get_body_measurement |
Get body measurements |
Development
uv sync # Install dependencies
uv run pre-commit install # Install pre-commit hooks
uv run pytest # Run tests
uv run ruff check # Lint
uv run ruff format # Format
uv run ty check # Type check
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file whoop_client-0.1.0.tar.gz.
File metadata
- Download URL: whoop_client-0.1.0.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
865d05d2a11cff9f297dd4d08b0fd3f24ef791bdeee43785edb03d7885e1f7ee
|
|
| MD5 |
de990e443783139b6627023a80bdfdcc
|
|
| BLAKE2b-256 |
e8786f569b163b0fc62526fa549d977fd83686fe48ec32f2879cc4f13453d27b
|
File details
Details for the file whoop_client-0.1.0-py3-none-any.whl.
File metadata
- Download URL: whoop_client-0.1.0-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4ca498c6350bc80e0eaa6495786296ed2d152a3e0bb7b65905b62ce6427793e
|
|
| MD5 |
e8043f460409dd3c76da5c813d077850
|
|
| BLAKE2b-256 |
65783da61903d210ebf886ec777b164dcb7257e86f74a89fe778f4baeae96f10
|