Skip to main content
Question

Athlete Limit Increase request (Client ID: 215634) — CoachCian

  • May 17, 2026
  • 0 replies
  • 2 views

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 /uploads with a TCX built from the run, then PATCH /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/routes on 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/token for 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_id per 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 #FC5200 with underline + the mandated wording. Links to https://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)

  • ASWebAuthenticationSession against strava.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_token returned by Strava is always persisted (old ones never reused). On 401 from 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_id reference 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/routes results 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.