Keely for developers
Build on a person’s numbers.
Keely has an HTTP API for apps, with OAuth 2.1 and permissions the person chooses. Your app asks a person for their Keely account on the consent page, they tick what it may read, and it reads it at https://meetkeely.com/api/v1. The answers are the summaries the Keely app backs up: each morning’s Recovery with what moved it, sleep, Load, stress and workouts. Never raw heart data, which stays on their iPhone.
Updated
On this page
What you can build
Keely turns a person’s Polar Loop into four daily numbers, computed on their iPhone: Recovery, Load, Stress and Sleep, with HRV, resting heart rate, breathing rate, skin temperature, sleep stages and workouts behind them. The API gives your app those numbers for the people who connect it, so it can know the person it serves:
- Mornings. Each morning’s Recovery (0–100 %, against the person’s own 30-night normal), what moved it, and the night behind it: HRV, resting heart rate, breathing rate, skin temperature, sleep stages, sleep against need, and regularity.
- Training. Each day’s Load and its target range, time in heart-rate zones, Balance (this week against the three before), and every workout with its sport, times, Load, heart rate and zones.
- Stress. Each day’s averages (day, night, and while still), minutes at each level, and the moments that stood out.
- The journal. What the person noted, as tags over time windows, and, when they ask your app to, entries your app adds. Only while they share their journal in the Keely app.
Three things hold for everything the API answers:
- Summaries only, never raw heart data. Heart-rate readings and beat intervals never leave the person’s iPhone, and no endpoint returns them. The finest grain is a night, a day, a workout, or a stress moment.
- The person chooses what you get. They tick scopes on the consent page, and they can narrow or end them at any time in the Keely app or at meetkeely.com/assistants.
- Nothing is made up. What isn’t recorded is
null, with a reason where there is one. What you’re not allowed to read is an error, never an empty answer. Every answer says when its data was last current (as_of) and links to how every number is computed.
Quickstart
Once your app is registered and you have its client_id, five steps take it from a person’s consent to their morning. Until Keely approves the app, the person is you: a new app connects only its developer’s account.
- Send the person to authorize. Make a PKCE
code_verifier, itscode_challengeand astate, and open the authorization endpoint. The person signs in with their Keely account, ticks what your app may read, and comes back to yourredirect_uriwithcodeandstate. Authorization has every parameter.Open https://zndhrjuvjoxbcdmwzeim.supabase.co/auth/v1/oauth/authorize ?client_id=YOUR_CLIENT_ID &redirect_uri=https://example.com/callback &response_type=code &code_challenge=CODE_CHALLENGE &code_challenge_method=S256 &state=STATE &scope=email - Exchange the code for tokens. A confidential client authenticates with its secret; a public client leaves out
-uand sends-d client_id=YOUR_CLIENT_IDinstead. The answer holds anaccess_tokengood for an hour and arefresh_token.Request curl -X POST https://zndhrjuvjoxbcdmwzeim.supabase.co/auth/v1/oauth/token \ -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \ -d grant_type=authorization_code \ -d code=CODE \ -d redirect_uri=https://example.com/callback \ -d code_verifier=CODE_VERIFIER - Read who connected, and what they allowed.
person_idis your key for the person, andscopesis what they ticked, which may be less than you asked for. GET /v1/me.Request curl https://meetkeely.com/api/v1/me \ -H "Authorization: Bearer ACCESS_TOKEN" - Read this morning. The latest morning and the day it began: Recovery with what moved it, the night, sleep, Load, stress and workouts, under the scopes the person allowed. GET /v1/days/latest.
Request curl https://meetkeely.com/api/v1/days/latest \ -H "Authorization: Bearer ACCESS_TOKEN" - Keep up. Poll the changes feed for what changed since your last read, once an hour or once a day, or subscribe to events and be told at once.
Request curl "https://meetkeely.com/api/v1/changes?since=2026-09-27T06:00:00Z" \ -H "Authorization: Bearer ACCESS_TOKEN"
Key facts
- Base URL
https://meetkeely.com/api/v1- Sign-in
- OAuth 2.1 with PKCE, on Keely’s authorization server
- Permissions
- Six scopes, chosen by the person on the consent page
- Format
- JSON; local dates, UTC times, units in field names
- Reference
- /openapi.json, OpenAPI 3.1
- Register
- meetkeely.com/developers/apps
- Cost
- Free
Questions
Does it cost anything?
No. The API is free, like Keely and the connector. There’s no paid tier and no quota beyond the rate limit, and approval costs nothing either.
Can I get raw heart-rate data?
No, never. Heart-rate readings, beat-to-beat intervals and movement never leave the person’s iPhone; Keely’s account holds only the summaries, and the API answers only those. If your app needs raw data, it needs its own sensor.
Can my app write data?
Only to the journal, with journal:write, and only while the person shares their journal in the Keely app: entries and tags, when the person asks your app to log something, and deleting what your app added. Nothing else can be written: scores, nights, days and workouts are the Keely app’s.
How do people disconnect my app?
In the Keely app, under Settings › Privacy › Apps and assistants, or at meetkeely.com/assistants. Either revokes the grant at once: the API refuses the token from then on, and refresh stops working. Deleting their Keely account ends every connection too. Your app then deletes what it holds (rule 3).
Do webhooks carry health data?
No. A webhook says what changed and for whom: an event type, the person’s id, a date or an id, and links. Never a score, a heart rate or a minute of sleep. Your app fetches those from the API with the person’s token, under the permissions they chose, exactly as if it had polled. So a leaked webhook secret leaks nothing but the fact that something changed.
What if my endpoint is down?
Keely retries each delivery after 1, 5 and 30 minutes, then 2 and 12 hours, and marks it failed after that; a subscription that fails 20 times in a row reads Failing in the portal until one delivery succeeds. When you’re back, read what you missed: GET /v1/events?since=<the last id you saw> for the last 30 days of events, or GET /v1/changes?since=<time> for the rows themselves, at any age.
Is Keely a medical device? What about HIPAA?
No. Keely’s numbers are wellness estimates from a consumer band, not medical measurements, and the API gives no medical advice. Keely isn’t a covered entity under HIPAA, and its summaries aren’t protected health information when they reach your app; what they are under the laws that apply to you (consumer health data, in several US states) is yours to handle. Say where you show them that they aren’t medical advice (rule 7).