Scopes¶
A scope is a category of information and a verb. Your app requests the categories it uses; the user sees one line per category on the consent screen, with your reason under it, and your token reaches the endpoints of those categories and nothing else. Request less, and the screen is shorter.
The scopes¶
| Scope | What it reaches | What the user reads |
|---|---|---|
activities:read |
Activities, sources and uploads, tests, traces, markers, max efforts, the metabolic map, training zones, the intensity-duration model, the template week, sports and tags: everything under /activities/, /tests/, /traces/ and the derived endpoints under /profile/. |
Read your activities, tests, traces and the training analysis built from them, over time. Training analysis might use your wellness data as well. |
activities:write |
Uploads, app metadata, tests, traces, markers and max efforts: creating, changing and deleting them. | Upload activities and record tests, traces and thresholds. |
wellness:read |
Every daily measure except the menstrual cycle day: GET /api/v1/dailies/{measure}. |
Read your daily wellness, such as sleep, heart-rate variability and body composition, over time. Does not include menstrual cycle data. |
wellness:write |
Recording and deleting those measures. | Record daily wellness on your behalf. |
reproductive_health:read |
GET /api/v1/dailies/menstrual_cycle_day. Standalone: it neither needs nor implies wellness. |
Read your menstrual cycle. |
reproductive_health:write |
Recording and deleting the cycle day. | Record your menstrual cycle on your behalf. |
workouts:read |
The user's scheduled workouts. | See your planned workouts. |
workouts:write |
Scheduling, changing and deleting workouts, which sends them to the user's connected devices. | Plan workouts on your calendar and send them to your connected devices. |
sharing:read |
Who shares data with the user and whom the user shares with: the users and teams listings, team rosters, and POST /api/v1/oauth/delegated-token. |
See who shares their data with you and act on their behalf, and see whom you share with. |
sharing:write |
Creating, updating and deleting managed accounts, and authorizing or revoking a team. | Change who you share your data with, and manage the accounts you created. Includes deleting those accounts. |
openid |
sub on userinfo and the ID token. |
Sign you in with your SweatStack account. |
profile |
The name claims: name, given_name, family_name. |
See your name. |
email |
email on userinfo. |
See your email address. |
offline_access |
A refresh token for PKCE clients. Clients with a client secret always get one. | Keep access while you are not using the app. |
Every endpoint's scope is in the API reference, and a 403
names the scope the token lacks.
A few endpoints need a valid token and no scope: GET /api/v1/profile/status,
POST /api/v1/portal/sessions and GET /api/v1/oauth/principal-token.
What the training analysis reveals¶
A model may use any value the user stored. What your app can see is what the consent line
names. The metabolic map and the zones use the user's body mass and resting heart rate, and
they do not echo them: there is no inputs field. Two values are nevertheless derivable from
activities:read alone, because the sport's own units need them; the consent line says that
training analysis uses wellness data, and this is the exact list:
- Body mass, from the VO2max the map publishes both absolute (mL/min) and relative to body mass (mL/kg/min).
- Resting heart rate, from heart-rate zones, which are cut on heart-rate reserve.
Nothing else about the user's wellness is derivable through an activities endpoint, on any date. Body composition, sleep, heart-rate variability and stress may steer a model and never come back out. The menstrual cycle day and the email address are never exposed through any other scope, in any form. If you find a wellness value reachable through an activities endpoint that is not one of the two above, tell us: we treat it as a vulnerability.
Purposes¶
For every category your app requests, except the identity scopes openid and profile and
offline_access, you write one sentence under What your app uses in the app's settings: why your app needs it. The user
reads it on the consent screen as a "Purpose" line under the category, marked as your words. One purpose per
category, 20 to 160 characters, plain text, no links.
Purposes are optional while only you connect to your app. Once anyone else can (your app is public), a request for a category without a purpose shows the user a "not ready to connect yet" page instead of the consent screen. The owner never meets that page, so test with a second account, and use Preview the consent screen on the edit form to read your purposes as the user will. What makes a good purpose.
Consent grows, it never shrinks¶
When your app asks for a scope the user has not granted yet, the consent screen shows only the new lines, with what they already allowed listed below. On consent, the grant becomes the union of old and new. A later request for fewer scopes never removes any: two flows of one app cannot cancel each other's grant, and a refresh token minted by either keeps its scopes. The user revokes your app as a whole, under Privacy.
Acting for someone else¶
A delegated token (a coach for an athlete, a manager for a managed account) never carries more
than the token it was minted from, and never email, sharing or offline_access. For a
consented grant it carries the grant intersected with your token; for a managed account it
carries your token minus those three. openid and profile ride with every grant, so
userinfo works on a delegated token and returns the athlete's id and name, never their email.
The endpoints are in the quick reference.
Before October 2026: data:read and data:write¶
Until plan 077 shipped, every app requested one of two bundles. They are retired. An app registered before the release may keep sending them until the end of the window named in the changelog; a request that carries one is read as the categories the bundle reached:
| You send | SweatStack reads |
|---|---|
data:read |
activities:read wellness:read reproductive_health:read workouts:read sharing:read |
data:write |
activities:write wellness:write reproductive_health:write workouts:write sharing:write |
profile together with a bundle |
openid profile email sharing:read sharing:write |
A request without a bundle is taken as it is, so profile on its own means the name only, as
OpenID says; add email for the address. Your app announces its move by dropping the bundle.
An app registered after the release gets invalid_scope for a bundle. Tokens and refresh tokens
issued before the release keep working: grants were translated in place, so no user re-consents.