403 with code missing_scope — and the error message names the scope
that was missing.
Grant the narrowest set of scopes your integration needs.
The scopes
Legacy aliases
Keys created before scoped permissions existed carry a coarseread, write, or
admin scope. These still work and are expanded automatically:
You don’t need to migrate old keys. When you create a new key, pick the precise
scopes instead.
The privacy ceiling on activity data
activities:read never exposes more than a coach in the same organization
would see for that athlete. Every activity is filtered through the athlete’s own
privacy settings before it leaves the API: fields an athlete has chosen to keep
private (pace, map, heart rate, and so on) are removed, and activities they have
hidden are omitted entirely.
Athletes can also mark individual activities as private from the mobile app,
independent of their global privacy settings. A per-activity opt-out is treated
like any other privacy filter: the activity is omitted from GET /activities
list results, and GET /activities/{activity_id} returns 404 for it.
This means two keys with the same scope can receive different data for the same
athlete over time, as that athlete adjusts their privacy settings. Build for a
field being absent rather than assuming a fixed shape.