All integrations

WHOOP API integration

The WHOOP your user already wears, behind the same connect call as every watch we support. They authorise once on a screen we host, and their workouts, sleep and recovery start arriving.

From 32.50 € a month billed annually, 30 days to change your mind.

your whoop user finishes a session — this is all you write

// decrypt() and stridee() are in /docs
export async function onStrideeEvent(rawBody, res) {
  const event = await decrypt(rawBody);

  if (event.type === 'activity.created' && event.data.file) {
    // event.data.device → "WHOOP"

    // A FIT file, written by us from WHOOP’s summary.
    const file = await stridee('GET', event.data.file.url);
    await saveActivity(event.user_id, file);
  }

  res.json({ nonce: event.nonce });
}

A WHOOP workout finishes. An activity.created event carrying WHOOP’s own summary, sealed to your public key.

  • Sport on one vocabulary, with WHOOP’s own sport name — “Weightlifting”, “Yoga” — as the workout’s name
  • Start time, duration and WHOOP’s own id for the workout
  • A FIT file we write from WHOOP’s summary: heart rate, energy and time in each heart-rate zone — no GPS track, no per-second samples
  • Sleep with its stages, daily recovery with HRV and resting heart rate, and the day’s strain, as wellness events

The WHOOP integration you’re not writing. The registration, the consent screen and the token refresh are ours.

01

Start capped at ten members

Anyone can create a WHOOP app, and a new one may connect ten members. Past that is a review by WHOOP, and each larger tier is another one. The whole app also shares 100 requests a minute and 10,000 a day, so the budget you test against is the budget every user you ever connect draws from. Through us it is a string in a connect call.

02

Never lose a refresh race

Access tokens last an hour, and a refresh token is replaced every time it is used. Two workers that refresh the same member at once both send the old one; one wins, the other is holding a token that no longer exists, and that member has to reconnect. So every refresh has to go through one lock per member, in every environment.

03

Fetch, re-fetch and reconcile

A WHOOP webhook carries an id and nothing else. The recovery webhook carries the id of the sleep it belongs to, so reaching the recovery is two calls. The day’s strain has no webhook at all. And a score arrives as PENDING_SCORE and settles later, so each record is read more than once and reconciled. We do that and send you one record that updates.

All of it is one POST /v1/connect naming whoop, and a webhook handler you write once for every provider.

Connect a device

your whoop user finishes a session — this is all you write

// decrypt() and stridee() are in /docs
export async function onStrideeEvent(rawBody, res) {
  const event = await decrypt(rawBody);

  if (event.type === 'activity.created' && event.data.file) {
    // event.data.device → "WHOOP"

    // A FIT file, written by us from WHOOP’s summary.
    const file = await stridee('GET', event.data.file.url);
    await saveActivity(event.user_id, file);
  }

  res.json({ nonce: event.nonce });
}

What WHOOP covers. Nothing is marked live unless an endpoint serves it today.

  • ConnectLive today
  • ActivitiesLive today
  • WellnessLive today
  • Workout pushThe provider doesn’t expose it

Every WHOOP device. The link is with the athlete’s account, not a watch, so models released after you ship reach you unchanged.

Current

  • WHOOP 5.0
  • WHOOP MG

Previous generation

  • WHOOP 4.0
Pricing

Two weeks free. Then from 32.50 € a month.

Checkout is the signup. No waitlist, no sales call.

  • Garmin, COROS, Polar, Wahoo, Zepp, Hammerhead, Fitbit, Suunto, WHOOP and Apple Watch behind one integration
  • Every endpoint on every plan — never priced per call
  • 14 days free, and no card charged until they are up
  • 30-day money-back guarantee

Cancel any time from the Stripe billing portal, or email [email protected] within 30 days and we refund you.

Plans start at

32.50 €/month, billed annually

Or 39 €/month, month to month. Paying annually gets you two months free.

Hacker, Startup, Scale and Enterprise differ on how many of your users may connect a watch. The API is the same on every plan.

See the plans

14-day free trial · cancel any time

We create the account on the email you pay with, automatically. Sign in at platform.stridee.com/login. Nothing to wait for.

WHOOP API questions

No. That is the point of the integration. We hold the WHOOP Developer Platform registration, the client credentials and the redirect URI; you call POST /v1/connect with your own id for your own user and redirect their browser to the URL that comes back. There is no WHOOP secret in your environment, no callback route in your router, and no WHOOP app review of your own. WHOOP does cap how many members one app may connect and raises that cap by review, so tell us ahead of a large launch.

Two weeks free, then from 32.50 € a month billed annually — or 39 € a month with no year to commit to — for the whole API, every provider and every endpoint, with no charge for calls. What separates the plans is how many of your users may connect a watch. Hacker is up to 100, for a project and its first users; Startup covers up to 500; Scale includes 1,500 and bills the ones past that at a published per-user rate, with no ceiling; Enterprise is a contract with a better rate again; and none of them charges for calls, activities or endpoints. The usual price for a unified wearable API starts in the hundreds of dollars a month and charges again for each connected user, which is a pricing model that punishes exactly the thing you are trying to do. There is a 30-day money-back guarantee on any charge, and cancelling is a button in the Stripe billing portal; access ends when the period does.

You get push, not polling. When an athlete finishes a workout, WHOOP notifies us and we send you an activity.created delivery — sealed to your public key as a JWE and signed with a detached JWS you verify against our published JWKS. Latency is whatever WHOOP takes to process the upload from the watch, which is theirs to own and typically a matter of minutes. You never write a polling loop and never hold a rate-limit budget.

There is no API key anywhere in this, in either direction. You authenticate to us with an Ed25519 signature over the request itself — RFC 9421 HTTP Message Signatures — using a private key that never leaves your machine, so there is no bearer token sitting in a log line, a CI variable or a backup. And we never hand you the provider's own credentials either.

Every strap that syncs to the WHOOP app, because the integration is with the WHOOP account rather than with a strap. WHOOP 5.0, WHOOP MG and WHOOP 4.0 all reach you the same way, and a model released next year works on the day it ships. SpO₂ and skin temperature need a 4.0 or newer, because older straps do not measure them. The device on a delivery reads “WHOOP”: the API does not say which strap it was.

Yes, the last five years. Connecting replays up to five years of workouts, sleeps, recoveries and daily cycles into your event stream as ordinary deliveries, with no second code path on your side. The one caveat is timing: history goes through the same budget as live data, which WHOOP sets at 100 requests a minute for the whole application, so a long history arrives over a quarter of an hour or so, newest month first, rather than at the moment they consent.

Yes, the daily ones. Recovery arrives as a wellness record of kind hrv: HRV as RMSSD in milliseconds and resting heart rate, plus SpO₂ and skin temperature on a 4.0 or newer, with the 0–100 recovery score in the record’s summary as score.recovery_score. Day Strain, on WHOOP’s 0–21 scale, is in the summary of the daily record beside the day’s kilojoules; steps and average and maximum heart rate are promoted fields there. That daily record is WHOOP’s cycle, which runs from one sleep to the next rather than midnight to midnight, and it updates until the cycle closes. The Strain of a single workout is not delivered.

Yes, and it is one we write. WHOOP exports no workout file: its API returns a scored summary, so we write that summary into a FIT file and a WHOOP workout arrives in the same shape as everyone else’s. It holds the sport, start time and duration, average and maximum heart rate, energy, time in each heart-rate zone, and distance and elevation gain when WHOOP has them. It holds no GPS track and no per-second samples, because a strap has no GPS and the API exposes no streams. A workout is delivered once WHOOP has scored it.

One wellness record per sleep, and a nap is its own record. Each carries the time in light, deep (WHOOP’s slow-wave), REM and awake, WHOOP’s sleep performance percentage as the sleep score, and respiratory rate; sleep need, consistency and efficiency are in the record’s summary. When WHOOP re-scores a sleep you get wellness.updated for the same record. Weight comes from the member’s WHOOP profile, read when they connect. Stress, VO₂max, continuous heart rate, journal entries and WHOOP’s Healthspan and lab features are not in WHOOP’s API, so they are absent rather than estimated.

No, and not eventually either. A WHOOP strap has no screen to show a step on, and WHOOP’s API has no call that receives a structured workout, so there is nothing to build against. A workout call naming this provider comes back as a 422 rather than half-working, which is why the table above marks workout push as unavailable rather than planned.

The full documentation is public and needs no account. Still have questions? Ask us in Discord

One integration, not ten. Same event shape, same handler, same plan. Your second provider is a string change — or, for Apple Watch, a Swift package.

GarminCOROSPolarWahooZeppHammerheadFitbitSuuntoApple Watch