wahoolib
wahoolib is a typed Python client and Typer-based CLI for the Wahoo Fitness Cloud API. It streamlines OAuth 2.0 login, token refresh, and the full suite of REST endpoints (users, plans, routes, power zones, workouts, summaries, uploads, and deauthorization).
This package is also a Claude Code plugin that provides AI-assisted guidance for Wahoo API integration.
Features
- OAuth helpers to build authorization URLs, exchange codes, refresh tokens, and plug in PKCE.
- Auto-refreshing API client with typed Pydantic v2 models for every major resource.
- Helpers for encoding and uploading plan JSON, route FIT files, and workout result FIT files.
- Batteries-included CLI mirroring the library functionality for quick experimentation.
Installation
# PyPI
pip install wahoolib
# Or with uv
uv pip install wahoolib
The CLI installs automatically and exposes the wahoolib entry point; you can also run it without a global install via uv run wahoolib ... or pipx run wahoolib ....
Usage (Library)
from wahoolib import (
EncodedFile,
PlanCreateRequest,
TokenSet,
WahooAPIClient,
WahooOAuthClient,
)
oauth = WahooOAuthClient(
client_id="your-client-id",
client_secret="your-client-secret",
redirect_uri="https://your-app.example.com/oauth/callback",
)
print("Visit:", oauth.authorization_url(["user_read", "workouts_read"], state="opaque"))
# After redirect, exchange the code
tokens = oauth.exchange_code("returned-code")
with WahooAPIClient(tokens, oauth_client=oauth) as client:
me = client.get_user()
plan = client.create_plan(
PlanCreateRequest(
file=EncodedFile.from_path("structured-workout.json", media_type="application/json"),
external_id="plan_42",
provider_updated_at=me.updated_at or me.created_at,
)
)
print("Uploaded plan", plan.id)
CLI Quickstart
The CLI mirrors the library’s capabilities and is ideal for quick experimentation or scripting:
# Generate an authorization URL
uv run wahoolib auth url --client-id YOUR_ID --redirect-uri https://example.com/callback --scope user_read --scope workouts_read
# Exchange the returned code and write the token payload to disk
uv run wahoolib auth exchange --client-id YOUR_ID --redirect-uri https://example.com/callback --code AUTH_CODE --output token.json
# Fetch the current user profile with a stored token set
uv run wahoolib user get --token-file token.json
# List workouts with pagination parameters
uv run wahoolib workouts list --token-file token.json --page 1 --per-page 10
All commands also accept --access-token / --refresh-token pairs if you prefer supplying tokens inline. Add --auto-refresh, --client-id, and --redirect-uri when you want the CLI to refresh access tokens automatically.
Subcommands at a glance
auth: OAuth helper utilities (url, exchange, refresh).
user: Fetch and update profile information.
plans: Upload, list, update, and delete structured workout plans.
routes: Manage route FIT files pushed to the Wahoo cloud.
power-zones: Create, update, list, and delete power zone configurations from JSON payloads.
workouts: List workouts, fetch details, create/update/delete entries, upsert summaries, and upload FIT activity files.
deauthorize: Revoke your application token set in the Wahoo cloud.
Environment Variables
The CLI automatically reads these variables when present:
WAHOO_CLIENT_ID – defaults --client-id
WAHOO_CLIENT_SECRET – defaults --client-secret
WAHOO_REDIRECT_URI – defaults --redirect-uri
Export them once and omit the corresponding options on every command.
Tests
uv run pytest
The test suite uses pytest-httpx to stub HTTP calls, so no live API access is required.
Development
uv pip install -e .[dev]
uv run ruff check .
uv run mypy src/wahoolib
uv run pytest --cov=src/wahoolib --cov-report=term-missing
Claude Code Plugin
This repository doubles as a Claude Code plugin. When installed, it provides the wahoo-api skill that guides Claude through Wahoo API integration tasks.
Install the Plugin
# In Claude Code
/plugin install parkerhancock/wahoolib
What the Skill Provides
- OAuth 2.0 flow guidance (authorization URLs, token exchange, refresh)
- Endpoint documentation for users, plans, workouts, routes, power zones
- Rate limit awareness (sandbox vs production)
- Troubleshooting for common errors (401, 403, 404, 429)
- CLI command examples using the bundled
wahoolib library
Plugin Structure
wahoolib/
├── .claude-plugin/
│ └── marketplace.json # Plugin manifest
├── skills/
│ └── wahoo-api/
│ ├── SKILL.md # Main skill documentation
│ └── references/
│ └── api_reference.md
└── src/wahoolib/ # Python library
License