home / skills / openclaw / skills / whoop-central

whoop-central skill

/skills/4xiomdev/whoop-central

This skill helps you access WHOOP data such as sleep, recovery, strain, and workouts via the v2 API for insights.

npx playbooks add skill openclaw/skills --skill whoop-central

Review the files below or copy the command above to add this skill to your agents.

Files (15)
SKILL.md
8.7 KB
---
name: whoop
description: WHOOP Central - OAuth + scripts to fetch WHOOP data (sleep, recovery, strain, workouts). Use when user asks about their sleep, recovery score, HRV, strain, or workout data.
version: 1.0.2
metadata:
  clawdbot:
    emoji: "🏋️"
    requires:
      bins: ["node", "openssl"]
---

# WHOOP Central

Access sleep, recovery, strain, and workout data from WHOOP via the v2 API.

## Quick Commands

```bash
# 1) One-time setup (writes ~/.clawdbot/whoop/credentials.json)
node src/setup.js

# 2) Recommended: Get tokens via Postman (see Auth section), then verify
node src/verify.js
node src/verify.js --refresh

# Prompt-friendly snapshot (includes last workout)
node src/today.js

# Daily summary (all metrics)
node src/summary.js

# Individual metrics
node src/recovery.js
node src/sleep.js
node src/strain.js
node src/workouts.js

# Bulk import to ~/clawd/health/logs/whoop/*
node src/import-historical.js
```

## Data Available

| Metric | Data Points |
|--------|-------------|
| **Recovery** | Score (0-100%), HRV, resting HR, SpO2, skin temp |
| **Sleep** | Duration, stages (REM/deep/light), efficiency, performance |
| **Strain** | Daily strain (0-21), calories, avg/max HR |
| **Workouts** | Activity type, duration, strain, calories, HR |

## Recovery Score Guide

- đź’š **67-100%** Green - Ready to perform
- đź’› **34-66%** Yellow - Moderate readiness
- ❤️ **0-33%** Red - Focus on recovery

## Setup

### 0. Requirements

- Node.js 18+ (this repo uses ESM)
- `openssl` (only needed for the optional `auth.js` flow when using `https://localhost`; Postman auth does not need it)

### 1. Create WHOOP Developer App

1. Go to https://developer.whoop.com/
2. Sign in with your WHOOP account
3. Create a new App
4. Add these Redirect URIs (exact match; no extra trailing slashes):
   - Postman browser callback (recommended auth path):
     ```
     https://oauth.pstmn.io/v1/browser-callback
     ```
   - Optional local callback (only used by `auth.js`):
     ```
     https://localhost:3000/callback
     ```
   You can keep both registered at the same time.
5. Copy the Client ID and Client Secret

Team note: this skill does **not** ship any client credentials. Each user can create their own WHOOP app,
or (if you trust each other) a team can share one app's `client_id`/`client_secret` and let multiple WHOOP
accounts authorize it.

### 2. Save Credentials (recommended: interactive)

Run:
```bash
node src/setup.js
```
This writes `~/.clawdbot/whoop/credentials.json` (and optionally `token.json` if you paste tokens).

### 3. Authenticate (Recommended: Postman)

Postman is the most reliable bootstrap for many accounts because WHOOP may block browser-like traffic
to the OAuth endpoints (or behave differently depending on headers).

Postman checklist (don’t skip these):
- WHOOP dashboard Redirect URIs include:
  - `https://oauth.pstmn.io/v1/browser-callback`
- Postman OAuth settings:
  - Scopes include `offline` (or you won’t get a `refresh_token`)
  - Client Authentication is **Send client credentials in body** (`client_secret_post`)

1) In WHOOP dashboard, ensure you registered the Postman callback Redirect URI:
```text
https://oauth.pstmn.io/v1/browser-callback
```

2) In Postman:
- Create an Environment and set variables:
  - `ClientId` = your WHOOP client id
  - `ClientSecret` = your WHOOP client secret
- Open the WHOOP API collection (or any request), then open the Authorization tab:
  - Type: OAuth 2.0
  - Add auth data to: Request Headers
  - Grant Type: Authorization Code
  - Callback URL: check **Authorize using browser**
  - Auth URL:
    ```
    https://api.prod.whoop.com/oauth/oauth2/auth
    ```
  - Access Token URL:
    ```
    https://api.prod.whoop.com/oauth/oauth2/token
    ```
  - Client ID: `{{ClientId}}`
  - Client Secret: `{{ClientSecret}}`
  - Scope (space-delimited): include `offline` plus any read scopes you need, e.g.:
    ```
    offline read:profile read:sleep read:recovery read:workout read:cycles read:body_measurement
    ```
  - State: any 8+ chars (e.g. `loomingState`)
  - Client Authentication: **Send client credentials in body**

3) Click "Get New Access Token", sign in to WHOOP, and click "Grant".

4) In Postman’s "Manage Access Tokens" modal:
- Click "Use Token" (so requests work)
- IMPORTANT: copy and save both:
  - `access_token`
  - `refresh_token`
  Postman often does not retain the refresh token for you later.

5) Save tokens to `~/.clawdbot/whoop/token.json`:
- Use `token.example.json` as a template
- Set:
  - `obtained_at` to current time in milliseconds
  - `redirect_uri` to:
    ```
    https://oauth.pstmn.io/v1/browser-callback
    ```

6) Verify (and test refresh):
```bash
node src/verify.js
node src/verify.js --refresh
```

### 4. Optional: Authenticate via `auth.js` (may fail on some accounts)

If you prefer a fully local OAuth loop (and WHOOP allows it), you can use `auth.js`.

Pre-req: add this redirect URI in WHOOP dashboard:
```text
https://localhost:3000/callback
```

Run:
```bash
WHOOP_REDIRECT_URI='https://localhost:3000/callback' node src/auth.js
```

If you need to do it from a phone/remote device:
```bash
WHOOP_REDIRECT_URI='https://localhost:3000/callback' node src/auth.js --manual
```

Note: for localhost HTTPS, the script generates a self-signed cert and your browser will show a TLS warning.
You must proceed past the warning so the redirect can complete.

### 4. Verify It Works

```bash
node src/verify.js
node src/summary.js
```

## Troubleshooting

### Browser shows `NotAuthorizedException` before the login page
This is a WHOOP-side block on browser User-Agents hitting `api.prod.whoop.com` OAuth endpoints.

- Use the updated `node src/auth.js` which bootstraps the login URL and sends your browser directly to `id.whoop.com`.
- If you still see it, try `node src/auth.js --manual` and open the printed URL.

### "redirect_uri not whitelisted"
1. Go to https://developer.whoop.com/
2. Edit your app
3. Ensure this EXACT URI is in Redirect URIs:
   ```
   https://oauth.pstmn.io/v1/browser-callback
   ```
   If you're using `auth.js` locally, also add:
   ```
   https://localhost:3000/callback
   ```
4. Save and try again

### Token Expired
Tokens auto-refresh on demand (no cron needed). If issues persist:
```bash
rm ~/.clawdbot/whoop/token.json
node src/auth.js
```

### "Authorization was not valid"
This usually means your access token is stale/invalidated (common if you re-auth or refresh tokens elsewhere; WHOOP refresh tokens rotate).

- Re-run `node src/auth.js`, or
- Copy the latest `access_token` + `refresh_token` from Postman into `~/.clawdbot/whoop/token.json` and update `obtained_at`.

### Auth from Phone/Remote Device
Use manual mode:
```bash
node src/auth.js --manual
```
Open the URL on any device, authorize, then copy the code from the callback URL.

### `error=request_forbidden` / "The request is not allowed"
This is WHOOP rejecting the authorization request after login/consent. Common causes:
- Redirect URI policy (WHOOP docs only mention `https://` or `whoop://` redirect URIs)
- App/account restrictions (membership/approval/test-user restrictions)
- Scope restrictions (try requesting fewer scopes)

If you suspect redirect URI policy, use an HTTPS tunnel:
```bash
# 1) Get a public HTTPS URL that forwards to localhost:3000 (example)
ngrok http 3000

# 2) Add the ngrok HTTPS URL + /callback to WHOOP dashboard Redirect URIs, then run:
WHOOP_REDIRECT_URI=https://YOUR-NGROK-DOMAIN.ngrok-free.app/callback node src/auth.js
```

If you suspect scope restrictions, try a minimal scope set:
```bash
WHOOP_SCOPES="read:profile" node src/auth.js
```

### If your WHOOP Redirect URL is `https://localhost:3000/callback`
This changes how the local callback server must run: it must be HTTPS (not HTTP).

The script supports this. Run:
```bash
WHOOP_REDIRECT_URI=https://localhost:3000/callback node src/auth.js
```
It will generate a self-signed cert locally and your browser will likely show a warning for `https://localhost`.
Proceed past the warning so the redirect can complete.

## JSON Output (for tooling)

These commands support:
- `--json` (single JSON blob)
- `--jsonl` (one JSON object per line; useful for piping)
- `--limit N` (where supported)
- Time filters (where supported): `--days N`, `--since 7d` / `12h`, `--start ISO`, `--end ISO`

```bash
node src/summary.js --json
node src/recovery.js --json --limit 1
node src/sleep.js --json --limit 1
node src/strain.js --json --limit 1
node src/workouts.js --json --limit 1

# Examples with filters
node src/sleep.js --json --days 7
node src/workouts.js --jsonl --since 30d
node src/recovery.js --json --start 2026-01-01T00:00:00Z --end 2026-02-01T00:00:00Z
```

## API Notes

- Uses WHOOP Developer API v2
- OAuth 2.0 authentication with refresh tokens
- Scopes: offline, read:recovery, read:sleep, read:workout, read:cycles, read:profile
- Token auto-refreshes when expired

Overview

This skill provides scripts and OAuth helpers to fetch WHOOP data (sleep, recovery, strain, workouts) using the WHOOP Developer API v2. It guides you through creating a WHOOP developer app, obtaining tokens (Postman recommended), and running command-line scripts to snapshot or import metrics. Use it to pull JSON or human-readable summaries for personal tracking or bulk archival.

How this skill works

The skill uses OAuth 2.0 to authorize access to a WHOOP account and stores credentials under ~/.clawdbot/whoop/. Command-line scripts query WHOOP endpoints for recovery, sleep, strain, and workout data and offer JSON/JSONL output for tooling. Tokens are auto-refreshed on demand and helper scripts verify and import historical data into a local directory.

When to use it

  • You want a programmatic snapshot of today’s WHOOP metrics (sleep, recovery, strain, last workout).
  • You need bulk export or archival of WHOOP history into local logs or tooling.
  • You want automated token management and verification for WHOOP API access.
  • You prefer JSON or JSONL output for integration with analytics pipelines.
  • You need troubleshooting guidance for common WHOOP OAuth issues.

Best practices

  • Register your own WHOOP developer app and keep client_id/client_secret private.
  • Use Postman to obtain initial access and refresh tokens; include the offline scope to receive refresh tokens.
  • Save credentials and tokens to ~/.clawdbot/whoop/credential and token.json as instructed so scripts can run non-interactively.
  • Verify tokens with the provided verify.js script and test refresh to confirm rotation handling.
  • Use --json or --jsonl flags when piping output into other tools or bulk import scripts.

Example use cases

  • Run node src/today.js to generate a prompt-friendly snapshot including last workout and recovery score.
  • Schedule a daily cron job that runs node src/summary.js --json and appends results to a local health log.
  • Import historical WHOOP data into ~/clawd/health/logs/whoop/ with node src/import-historical.js for backup or analysis.
  • Fetch a week of sleep data for a report: node src/sleep.js --json --days 7 and pipe into your analytics tool.
  • Use node src/recovery.js --json --limit 1 to display current recovery score and HRV for readiness checks.

FAQ

What if WHOOP blocks the OAuth request in a browser?

Use the auth.js bootstrap that sends your browser directly to id.whoop.com or perform token exchange via Postman. The README includes a manual auth flow and workarounds for blocked User-Agents.

How do I handle refresh token rotation?

Always copy the latest refresh_token from Postman into token.json if you re-auth elsewhere. The scripts auto-refresh on demand, but refresh tokens can rotate so re-run auth if you see invalid token errors.