Skip to main content
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.
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.

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:
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:
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

# 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).