Name | whoopy JSON |
Version |
0.3.0
JSON |
| download |
home_page | None |
Summary | Unofficial Client for the Whoop API |
upload_time | 2025-07-14 09:28:25 |
maintainer | Felix Geilert |
docs_url | None |
author | Felix Geilert |
requires_python | >=3.10 |
license | MIT |
keywords |
api
fitness
health
wearable
whoop
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Whoop Python Client
[](https://github.com/felixnext/whoopy/actions/workflows/python-package.yml)
[](https://badge.fury.io/py/whoopy)
[](https://pypi.org/project/whoopy/)
[](https://opensource.org/licenses/MIT)
An unofficial Python client for the [WHOOP API](https://developer.whoop.com/) with support for both OAuth and Personal API keys. Features async/await support, automatic token refresh, and comprehensive data models.
## Features
- 🚀 **Full API v2 Support** - Access cycles, sleep, recovery, workouts, and user data
- ⚡ **Async/Await Support** - High-performance async client with synchronous wrapper
- 🔄 **Automatic Token Management** - Token refresh and persistence out of the box
- 📊 **Pandas Integration** - Export data directly to DataFrames for analysis
- 🛡️ **Type Safety** - Comprehensive type hints and Pydantic models
- 🔁 **Retry Logic** - Built-in retry with exponential backoff
- 🐍 **Python 3.10+** - Modern Python with the latest features
## Installation
### Using pip
```bash
pip install whoopy
```
### Using uv (recommended)
```bash
uv add whoopy
```
### Development Installation
```bash
# Clone the repository
git clone https://github.com/felixnext/whoopy.git
cd whoopy
# Install with uv (recommended)
uv sync --all-extras
# Or install with pip
pip install -e ".[dev]"
```
## Quick Start
### 1. Get Your API Credentials
1. Go to the [WHOOP Developer Dashboard](https://developer-dashboard.whoop.com/)
2. Create a new application
3. Note your `client_id`, `client_secret`, and set `redirect_uri` to `http://localhost:1234`
### 2. Create Configuration
Create a `config.json` file:
```json
{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"redirect_uri": "http://localhost:1234"
}
```
> **Note**: The library also supports a nested config structure for backward compatibility:
> ```json
> {
> "whoop": {
> "client_id": "YOUR_CLIENT_ID",
> "client_secret": "YOUR_CLIENT_SECRET",
> "redirect_uri": "http://localhost:1234"
> }
> }
> ```
### 3. Run the Example
```bash
# Run the example script
uv run python -m tools.example
# Or if using standard Python
python -m tools.example
```
Note: The redirect uri will not exist. You need to copy the entire url from your browser and
paste it in the console. This will then handle the token exchange.
## Usage Examples
### Synchronous Usage (Recommended for Beginners)
```python
from whoopy import WhoopClient
from datetime import datetime, timedelta
# Initialize client (loads credentials from config.json)
client = WhoopClient.from_config()
# Get user profile
profile = client.user.get_profile()
print(f"Hello, {profile.first_name}!")
# Get recent recovery data
recoveries = client.recovery.get_all(
start=datetime.now() - timedelta(days=7),
end=datetime.now()
)
for recovery in recoveries:
print(f"Recovery: {recovery.score.recovery_score}%")
# Export to pandas DataFrame
df = client.sleep.get_dataframe(
start=datetime.now() - timedelta(days=30)
)
print(df.describe())
```
### Asynchronous Usage (Better Performance)
```python
import asyncio
from whoopy import WhoopClientV2
async def main():
# Use async context manager
async with WhoopClientV2.from_config() as client:
# Fetch multiple data types concurrently
profile, cycles, sleep = await asyncio.gather(
client.user.get_profile(),
client.cycles.get_all(limit_per_page=10),
client.sleep.get_all(limit_per_page=10)
)
print(f"User: {profile.first_name}")
print(f"Recent cycles: {len(cycles)}")
print(f"Recent sleep: {len(sleep)}")
# Run the async function
asyncio.run(main())
```
### Authentication Options
```python
# Option 1: Interactive OAuth flow (opens browser)
client = WhoopClient.auth_flow(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
redirect_uri="http://localhost:1234"
)
# Option 2: From existing token
client = WhoopClient.from_token(
access_token="YOUR_ACCESS_TOKEN",
refresh_token="YOUR_REFRESH_TOKEN",
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET"
)
# Option 3: From config files (recommended)
client = WhoopClient.from_config()
# Save credentials for later use
client.save_token(".whoop_credentials.json")
```
## Available Data Types
### User Data
- Profile information
- Body measurements
### Physiological Data
- **Cycles** - Daily physiological cycles
- **Recovery** - Recovery metrics including HRV, resting heart rate
- **Sleep** - Sleep stages, efficiency, and performance
- **Workouts** - Exercise activities with strain and heart rate data
## Development
### Setup Development Environment
```bash
# Clone the repository
git clone https://github.com/felixnext/whoopy.git
cd whoopy
# Install with development dependencies
uv sync --all-extras
```
### Running Tests
```bash
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=whoopy
# Run specific test file
uv run pytest tests/test_client.py
```
### Code Quality
```bash
# Run linting
uv run ruff check .
# Format code
uv run ruff format .
# Type checking
uv run mypy whoopy
```
### Building the Package
```bash
# Build wheel and sdist
uv build
# Install locally to test
uv pip install dist/whoopy-*.whl
```
## Data Explorer Tool
The package includes a Streamlit-based data explorer for visualizing your WHOOP data:
```bash
# Install explorer dependencies
uv sync --extra explorer
# Run the explorer
cd tools/explorer && uv run streamlit run explorer.py
```
### Explorer Features
- Interactive data visualization
- Date range filtering
- Export to CSV/Excel
- Recovery, sleep, and workout analysis

## API Reference
### Client Classes
- `WhoopClient` - Synchronous client (v2 API)
- `WhoopClientV2` - Async client (v2 API)
- `WhoopClientV1` - Legacy v1 client
### Main Methods
```python
# User data
profile = client.user.get_profile()
measurements = client.user.get_body_measurements()
# Cycles (daily summaries)
cycle = client.cycles.get_by_id(12345)
cycles = client.cycles.get_all(start="2024-01-01", end="2024-01-31")
# Sleep
sleep = client.sleep.get_by_id("uuid-here")
sleep_df = client.sleep.get_dataframe(start="2024-01-01")
# Recovery
recovery = client.recovery.get_for_cycle(12345)
recoveries = client.recovery.get_all()
# Workouts
workout = client.workouts.get_by_id("uuid-here")
workouts = client.workouts.get_by_sport("running", start="2024-01-01")
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
### Development Workflow
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes and add tests
4. Run tests and linting (`uv run pytest && uv run ruff check`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Disclaimer
This is an unofficial client for the WHOOP API. It is not affiliated with, endorsed by, or in any way officially connected to WHOOP. Use at your own risk.
## Support
- 📖 [Documentation](https://github.com/felixnext/whoopy#readme)
- 🐛 [Issue Tracker](https://github.com/felixnext/whoopy/issues)
- 💬 [Discussions](https://github.com/felixnext/whoopy/discussions)
## Acknowledgments
- Thanks to WHOOP for providing the [official API](https://developer.whoop.com/)
- Built with [aiohttp](https://docs.aiohttp.org/) and [pydantic](https://docs.pydantic.dev/)
Raw data
{
"_id": null,
"home_page": null,
"name": "whoopy",
"maintainer": "Felix Geilert",
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "api, fitness, health, wearable, whoop",
"author": "Felix Geilert",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/7f/03/22bfcb796c909234f3fcc19793e4f518c21c305babccacd63f4d6061d302/whoopy-0.3.0.tar.gz",
"platform": null,
"description": "# Whoop Python Client\n\n[](https://github.com/felixnext/whoopy/actions/workflows/python-package.yml)\n[](https://badge.fury.io/py/whoopy)\n[](https://pypi.org/project/whoopy/)\n[](https://opensource.org/licenses/MIT)\n\nAn unofficial Python client for the [WHOOP API](https://developer.whoop.com/) with support for both OAuth and Personal API keys. Features async/await support, automatic token refresh, and comprehensive data models.\n\n## Features\n\n- \ud83d\ude80 **Full API v2 Support** - Access cycles, sleep, recovery, workouts, and user data\n- \u26a1 **Async/Await Support** - High-performance async client with synchronous wrapper\n- \ud83d\udd04 **Automatic Token Management** - Token refresh and persistence out of the box\n- \ud83d\udcca **Pandas Integration** - Export data directly to DataFrames for analysis\n- \ud83d\udee1\ufe0f **Type Safety** - Comprehensive type hints and Pydantic models\n- \ud83d\udd01 **Retry Logic** - Built-in retry with exponential backoff\n- \ud83d\udc0d **Python 3.10+** - Modern Python with the latest features\n\n## Installation\n\n### Using pip\n\n```bash\npip install whoopy\n```\n\n### Using uv (recommended)\n\n```bash\nuv add whoopy\n```\n\n### Development Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/felixnext/whoopy.git\ncd whoopy\n\n# Install with uv (recommended)\nuv sync --all-extras\n\n# Or install with pip\npip install -e \".[dev]\"\n```\n\n## Quick Start\n\n### 1. Get Your API Credentials\n\n1. Go to the [WHOOP Developer Dashboard](https://developer-dashboard.whoop.com/)\n2. Create a new application\n3. Note your `client_id`, `client_secret`, and set `redirect_uri` to `http://localhost:1234`\n\n### 2. Create Configuration\n\nCreate a `config.json` file:\n\n```json\n{\n \"client_id\": \"YOUR_CLIENT_ID\",\n \"client_secret\": \"YOUR_CLIENT_SECRET\",\n \"redirect_uri\": \"http://localhost:1234\"\n}\n```\n\n> **Note**: The library also supports a nested config structure for backward compatibility:\n> ```json\n> {\n> \"whoop\": {\n> \"client_id\": \"YOUR_CLIENT_ID\",\n> \"client_secret\": \"YOUR_CLIENT_SECRET\",\n> \"redirect_uri\": \"http://localhost:1234\"\n> }\n> }\n> ```\n\n### 3. Run the Example\n\n```bash\n# Run the example script\nuv run python -m tools.example\n\n# Or if using standard Python\npython -m tools.example\n```\n\nNote: The redirect uri will not exist. You need to copy the entire url from your browser and\npaste it in the console. This will then handle the token exchange.\n\n## Usage Examples\n\n### Synchronous Usage (Recommended for Beginners)\n\n```python\nfrom whoopy import WhoopClient\nfrom datetime import datetime, timedelta\n\n# Initialize client (loads credentials from config.json)\nclient = WhoopClient.from_config()\n\n# Get user profile\nprofile = client.user.get_profile()\nprint(f\"Hello, {profile.first_name}!\")\n\n# Get recent recovery data\nrecoveries = client.recovery.get_all(\n start=datetime.now() - timedelta(days=7),\n end=datetime.now()\n)\n\nfor recovery in recoveries:\n print(f\"Recovery: {recovery.score.recovery_score}%\")\n\n# Export to pandas DataFrame\ndf = client.sleep.get_dataframe(\n start=datetime.now() - timedelta(days=30)\n)\nprint(df.describe())\n```\n\n### Asynchronous Usage (Better Performance)\n\n```python\nimport asyncio\nfrom whoopy import WhoopClientV2\n\nasync def main():\n # Use async context manager\n async with WhoopClientV2.from_config() as client:\n # Fetch multiple data types concurrently\n profile, cycles, sleep = await asyncio.gather(\n client.user.get_profile(),\n client.cycles.get_all(limit_per_page=10),\n client.sleep.get_all(limit_per_page=10)\n )\n \n print(f\"User: {profile.first_name}\")\n print(f\"Recent cycles: {len(cycles)}\")\n print(f\"Recent sleep: {len(sleep)}\")\n\n# Run the async function\nasyncio.run(main())\n```\n\n### Authentication Options\n\n```python\n# Option 1: Interactive OAuth flow (opens browser)\nclient = WhoopClient.auth_flow(\n client_id=\"YOUR_CLIENT_ID\",\n client_secret=\"YOUR_CLIENT_SECRET\",\n redirect_uri=\"http://localhost:1234\"\n)\n\n# Option 2: From existing token\nclient = WhoopClient.from_token(\n access_token=\"YOUR_ACCESS_TOKEN\",\n refresh_token=\"YOUR_REFRESH_TOKEN\",\n client_id=\"YOUR_CLIENT_ID\",\n client_secret=\"YOUR_CLIENT_SECRET\"\n)\n\n# Option 3: From config files (recommended)\nclient = WhoopClient.from_config()\n\n# Save credentials for later use\nclient.save_token(\".whoop_credentials.json\")\n```\n\n## Available Data Types\n\n### User Data\n- Profile information\n- Body measurements\n\n### Physiological Data\n- **Cycles** - Daily physiological cycles\n- **Recovery** - Recovery metrics including HRV, resting heart rate\n- **Sleep** - Sleep stages, efficiency, and performance\n- **Workouts** - Exercise activities with strain and heart rate data\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/felixnext/whoopy.git\ncd whoopy\n\n# Install with development dependencies\nuv sync --all-extras\n```\n\n### Running Tests\n\n```bash\n# Run all tests\nuv run pytest\n\n# Run with coverage\nuv run pytest --cov=whoopy\n\n# Run specific test file\nuv run pytest tests/test_client.py\n```\n\n### Code Quality\n\n```bash\n# Run linting\nuv run ruff check .\n\n# Format code\nuv run ruff format .\n\n# Type checking\nuv run mypy whoopy\n```\n\n### Building the Package\n\n```bash\n# Build wheel and sdist\nuv build\n\n# Install locally to test\nuv pip install dist/whoopy-*.whl\n```\n\n## Data Explorer Tool\n\nThe package includes a Streamlit-based data explorer for visualizing your WHOOP data:\n\n```bash\n# Install explorer dependencies\nuv sync --extra explorer\n\n# Run the explorer\ncd tools/explorer && uv run streamlit run explorer.py\n```\n\n### Explorer Features\n- Interactive data visualization\n- Date range filtering\n- Export to CSV/Excel\n- Recovery, sleep, and workout analysis\n\n\n\n## API Reference\n\n### Client Classes\n\n- `WhoopClient` - Synchronous client (v2 API)\n- `WhoopClientV2` - Async client (v2 API)\n- `WhoopClientV1` - Legacy v1 client\n\n### Main Methods\n\n```python\n# User data\nprofile = client.user.get_profile()\nmeasurements = client.user.get_body_measurements()\n\n# Cycles (daily summaries)\ncycle = client.cycles.get_by_id(12345)\ncycles = client.cycles.get_all(start=\"2024-01-01\", end=\"2024-01-31\")\n\n# Sleep\nsleep = client.sleep.get_by_id(\"uuid-here\")\nsleep_df = client.sleep.get_dataframe(start=\"2024-01-01\")\n\n# Recovery\nrecovery = client.recovery.get_for_cycle(12345)\nrecoveries = client.recovery.get_all()\n\n# Workouts\nworkout = client.workouts.get_by_id(\"uuid-here\")\nworkouts = client.workouts.get_by_sport(\"running\", start=\"2024-01-01\")\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n### Development Workflow\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes and add tests\n4. Run tests and linting (`uv run pytest && uv run ruff check`)\n5. Commit your changes (`git commit -m 'Add amazing feature'`)\n6. Push to the branch (`git push origin feature/amazing-feature`)\n7. Open a Pull Request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Disclaimer\n\nThis is an unofficial client for the WHOOP API. It is not affiliated with, endorsed by, or in any way officially connected to WHOOP. Use at your own risk.\n\n## Support\n\n- \ud83d\udcd6 [Documentation](https://github.com/felixnext/whoopy#readme)\n- \ud83d\udc1b [Issue Tracker](https://github.com/felixnext/whoopy/issues)\n- \ud83d\udcac [Discussions](https://github.com/felixnext/whoopy/discussions)\n\n## Acknowledgments\n\n- Thanks to WHOOP for providing the [official API](https://developer.whoop.com/)\n- Built with [aiohttp](https://docs.aiohttp.org/) and [pydantic](https://docs.pydantic.dev/)",
"bugtrack_url": null,
"license": "MIT",
"summary": "Unofficial Client for the Whoop API",
"version": "0.3.0",
"project_urls": {
"Changelog": "https://github.com/felixnext/whoopy/releases",
"Documentation": "https://github.com/felixnext/whoopy#readme",
"Homepage": "https://github.com/felixnext/whoopy",
"Issues": "https://github.com/felixnext/whoopy/issues",
"Repository": "https://github.com/felixnext/whoopy.git"
},
"split_keywords": [
"api",
" fitness",
" health",
" wearable",
" whoop"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "67ed9f8df00839401495e2dfebbdc0ca8c70cdc174a14dc9330a17798905101a",
"md5": "3edaae31ed2521fbf073be601ea58279",
"sha256": "e0422a40f3a7fd217c4cd43c190dd2190a958494d68225ac9563bfd208183773"
},
"downloads": -1,
"filename": "whoopy-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3edaae31ed2521fbf073be601ea58279",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 45883,
"upload_time": "2025-07-14T09:28:24",
"upload_time_iso_8601": "2025-07-14T09:28:24.444715Z",
"url": "https://files.pythonhosted.org/packages/67/ed/9f8df00839401495e2dfebbdc0ca8c70cdc174a14dc9330a17798905101a/whoopy-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "7f0322bfcb796c909234f3fcc19793e4f518c21c305babccacd63f4d6061d302",
"md5": "73e8029f7c6358bdfed8d1071352477c",
"sha256": "bf9fbb1c71159dc9299081da01263d1abbc0ef5b9cd7312dbc281ef7873e454a"
},
"downloads": -1,
"filename": "whoopy-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "73e8029f7c6358bdfed8d1071352477c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 44369,
"upload_time": "2025-07-14T09:28:25",
"upload_time_iso_8601": "2025-07-14T09:28:25.358312Z",
"url": "https://files.pythonhosted.org/packages/7f/03/22bfcb796c909234f3fcc19793e4f518c21c305babccacd63f4d6061d302/whoopy-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-14 09:28:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "felixnext",
"github_project": "whoopy",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "whoopy"
}