> ## Documentation Index
> Fetch the complete documentation index at: https://foreverbetter.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect a WHOOP

> How a signed-up user links their WHOOP in a few clicks, with no developer credentials required.

WHOOP connects through server-side OAuth. There are two ways to do it, depending on
who owns the WHOOP app:

* **First-party (consumer)**: a signed-up user connects their own WHOOP with one
  click. ForeverBetter's WHOOP app is configured on the server, so the user never
  sees a `client_id`/`secret`. This is the flow below.
* **Bring-your-own (integrator)**: your app owns a WHOOP app and passes its
  credentials on each call. See [Wearable onboarding](/wearable-onboarding).

<Note>
  First-party connect is available when the `wearables.whoop` entry in
  `GET /capabilities` reports `first_party_oauth: true`. When it does not, use
  bring-your-own mode and pass your WHOOP app's `client_id`/`secret` on start,
  callback, and refresh.
</Note>

## 1. Start the connection (no credentials)

Once the user is signed in and has a key, start a WHOOP connection with just the
provider. The server fills in its own WHOOP app:

```bash theme={null}
curl -s -X POST "$FB_API/connections/wearables/start" \
  -H "authorization: Bearer $FB_KEY" -H "content-type: application/json" \
  -d '{"user_id":"'$UID'","organization_id":"'$ORG'","source_provider":"whoop"}'
# → { "connection_type":"oauth", "authorization_url":"https://api.prod.whoop.com/oauth/oauth2/auth?...", "scopes":[...] }
```

## 2. Send the user to WHOOP

Redirect the user to `authorization_url`. They log into WHOOP and approve access.
WHOOP redirects back to the configured redirect URI with `?code=...`.

## 3. Complete the connection (just the code)

Hand the authorization `code` back. Again, no `client_id`/`secret` needed:

```bash theme={null}
curl -s -X POST "$FB_API/connections/wearables/callback" \
  -H "authorization: Bearer $FB_KEY" -H "content-type: application/json" \
  -d '{"user_id":"'$UID'","organization_id":"'$ORG'","source_provider":"whoop","code":"'$CODE'"}'
# → { "connection_type":"oauth", "external_account":{...}, "token_storage":"external_secret_store_required" }
```

The WHOOP tokens are exchanged server-side and handed to your secret store; they
are never persisted in the API's request path.

## 4. Sync and analyze

```bash theme={null}
# Pull normalized sleep, recovery, HRV, and workouts
curl -s -X POST "$FB_API/connections/wearables/sync" \
  -H "authorization: Bearer $FB_KEY" -H "content-type: application/json" \
  -d '{"user_id":"'$UID'","organization_id":"'$ORG'","source_provider":"whoop"}'

# Then run wearable analysis
curl -s -X POST "$FB_API/wearables/analyze" \
  -H "authorization: Bearer $FB_KEY" -H "content-type: application/json" \
  -d '{"user_id":"'$UID'","organization_id":"'$ORG'","source_ids":["..."]}'
```

Tokens expire; refresh them with `POST /connections/whoop/refresh` (first-party mode
needs only the `refresh_token`).
