Hello Strava team,
Requesting an athlete cap increase for CoachCian (Client ID: 215634).
What it does: iOS running app — pace coaching, planned workouts, Claude-powered training-plan generator, and a watchOS companion that records runs natively. When a run finishes, the app uploads the activity (full GPS track, heart-rate stream, per-lap stats, step results) to the user's own Strava so it sits alongside their other activities. Strava is the share endpoint, not a data source we read from for analytics.
How we use the Strava API
- Scope:
activity:write,read,read_all. We write the user's own completed runs and read so they can pick one of their own saved Strava routes as a route option for the next run. - Upload endpoint:
POST /uploadswith a TCX built from the run, thenPATCH /activities/{id}to enrich with description, gear and lap data. One upload per finished run, fired locally on the user's device. - Read endpoint:
GET /athlete/routeson demand only — when the user opens the route picker and taps "Strava" as the source. No background polling, no scheduled sync, no webhook subscription. - Token endpoint:
POST /oauth/tokenfor the initial code exchange and refreshes. - Data stored per user (on-device only, iOS Keychain or SwiftData): access token + refresh token + expiry, athlete id, display name, and the returned
activity_idper uploaded run so the History view can render a "View on Strava" link. No server-side storage — there is no CoachCian backend.
Compliance — brand (developers.strava.com/guidelines)
- Official orange "Connect with Strava" button from the 1.1 brand pack, unmodified, as the only entry point to OAuth.
- "Powered by Strava" orange horizontal logo (1.2 pack), unmodified, displayed in the Settings Strava section. Kept smaller than CoachCian's own branding and visually separate from it.
- "View on Strava" link surfaced from uploaded activities, styled in
#FC5200with underline + the mandated wording. Links tohttps://www.strava.com/activities/{id}. - No Strava marks used in the app icon, app name ("CoachCian") or anywhere implying we're an official Strava app.
Compliance — auth & transport (§§2.8, 5.2)
ASWebAuthenticationSessionagainststrava.com/oauth/authorize. Explicit per-user OAuth consent every time.- HTTPS only for every Strava request. Tokens encrypted at rest in iOS Keychain.
- Refresh handling: refresh only when within 5 minutes of expiry; the latest
refresh_tokenreturned by Strava is always persisted (old ones never reused). On401from any Strava endpoint we force-refresh once and retry, to handle out-of-band token invalidation cleanly.
Compliance — data handling (§§2.10, 5.4, 7.1, 2.14.5)
- Single-user display only. The app only ever shows or operates on the authenticated user's own Strava data — never aggregated, never cross-user, even for publicly viewable activities.
- Disconnect deletion. "Disconnect Strava" wipes access + refresh tokens from Keychain and clears every stored
activity_idreference from the on-device run history. Nothing per-user persists post-revocation. - Deletion-on-request. A user can clear all CoachCian data via iOS Settings → CoachCian → Reset, which deletes the SwiftData store and Keychain entries together.
- Cache TTL.
GET /athlete/routesresults are cached only for the lifetime of the route-picker screen — never longer than the 7-day cap, in practice seconds to minutes. - Granular permissions respected. The OAuth flow uses only the scopes listed above; we'll respect any future granular scope changes Strava ships.
- Security breach notification. We understand the 24-hour notification obligation under §2.8 and have a process to reach Strava developer support within that window if anything happens.
What CoachCian explicitly does not do (addressing the common rejection vectors head-on)
- No webhooks / no background polling — uploads + reads are purely user-initiated.
- No scraping or web data extraction (§2.14.9).
- No reverse engineering of any Strava endpoint or asset (§2.14.14).
- No AI/ML training on Strava data, directly or indirectly (§2.14.4). The Claude-powered features in the app receive only the user's own CoachCian-tracked workouts (distance/pace/HR from CoreLocation + HealthKit) — never Strava-sourced data.
- No aggregation, analytics, customer insights, or de-identified processing of Strava data (§2.14.7).
- No charge to users for any Strava-related functionality (§2.14.15). The app itself is free; no premium tier gates the Strava integration.
- Not competitive with Strava (§2.14.2). CoachCian is a coaching/training planner; we explicitly position Strava as the social/sharing destination for completed activities.
- No sharing of API credentials. Client secret lives in the app binary, per-user tokens never leave the user's device.
Why the increase: the app is in TestFlight with a small group (currently 5 internal testers, expanding to ~25 external testers as a closed beta over the next month). They're hitting the single-authorized-user limit when they tap Connect. I'd like the cap lifted so the closed-beta group — and a small public release once the integration stabilises — can connect their own Strava accounts. Happy to walk through the upload + disconnect flows end-to-end if useful.
Thanks for taking a look.
