Security

How we handle health data

Specific claims you can check, not reassurance. Where we're weaker than self-hosting, we say so.

What we actually store

This is the shortest list we could make it:

DataStored?Notes
Your email addressYesUsed for sign-in and billing notices.
WHOOP access + refresh tokensYes, encryptedAES-256-GCM under a key held in the environment, not in the database.
WHOOP account name, email, user idYesSo the dashboard can show which account is connected.
Your recovery, sleep, workout recordsNoFetched from WHOOP on demand and passed straight through. We keep no copy.
API keysHash onlySHA-256. The plaintext exists in one HTTP response and is never recoverable.
Which tools were called and whenYesTool name, duration, success — never the returned data.
Card detailsNoHandled entirely by Mollie. We never see a card number.
Your WHOOP passwordNeverYou authorise through WHOOP's own consent screen.

The most important row is the fourth. FitnessPeak is a pipe, not a warehouse. Your health records live at WHOOP and pass through us to your assistant. There is no historical archive here to breach.

Token encryption

WHOOP tokens are sealed with AES-256-GCM before they touch the database, under a key supplied through the environment. The stored form is v1.<iv>.<tag>.<ciphertext> — versioned so keys can be rotated later without guessing at the old layout. A database file on its own does not grant API access.

If the encryption key is unavailable, the server refuses to store tokens rather than falling back to plaintext.

API keys

  • 32 bytes of CSPRNG entropy — 256 bits — base64url encoded behind an fp_live_ prefix
  • Only SHA-256(key) is stored; we cannot show you a key twice because we don't have it
  • Lookup is a unique-indexed hash match, so there's no per-row comparison and no timing oracle
  • Revocation is immediate and permanent
  • Access logs redact anything matching fp_live_…

A leaked key could read your fitness data and nothing else. It cannot change your WHOOP account, cannot reach your card details, and cannot sign in to your dashboard.

Read-only, enforced upstream

FitnessPeak requests only WHOOP's read scopes: read:recovery, read:sleep, read:workout, read:cycles, read:profile, read:body_measurement, plus offline for refresh. Even a total compromise of our code could not write to your WHOOP account, because the token was never granted that power.

Transport and headers

  • HTTPS everywhere, HSTS with a one-year max-age, includeSubDomains and preload
  • Content-Security-Policy with script-src 'self' — no third-party scripts on any page
  • frame-ancestors 'none', object-src 'none', restrictive Permissions-Policy
  • No analytics or advertising trackers anywhere on the site

Rate limiting

120 MCP calls per minute per key. Sign-in links are capped per IP and per email address. Both return 429 with Retry-After.

Where self-hosting is stronger

Running your own WHOOP MCP server keeps your tokens on hardware you control. We cannot match that, and if it's your requirement you should self-host — we wrote the comparison ourselves.

Deleting everything

The delete button in your dashboard removes your user row, and every related table cascades from it: WHOOP connection, API keys, usage history, payment records. It is a real delete, not a flag. You can also revoke FitnessPeak's access from within WHOOP at any time, independently of us.

Reporting a vulnerability

Email security@fitnesspeak.app. We'll acknowledge within 72 hours. Please don't test against other people's accounts — if you need a second account to demonstrate something, ask and we'll set one up.

Machine-readable contact details: /.well-known/security.txt.

What we haven't done

FitnessPeak is a small independent product. We have no SOC 2 report, no penetration-test certificate, and no security team. If your threat model needs those, it needs a different vendor — or self-hosting.

Last updated 14 August 2026.