strava_client 2.3.1 copy "strava_client: ^2.3.1" to clipboard
strava_client: ^2.3.1 copied to clipboard

An unofficial Flutter client for the Strava V3 API: OAuth2 authentication with automatic token refresh, typed models, and repository-based endpoints.

strava_client #

pub package CI License: MIT

An unofficial Flutter client for the Strava V3 API.

It handles the OAuth2 flow (including the native Strava app on iOS), automatic token storage and refresh, and gives you typed models and repositories for the Strava endpoints.

  • 🔐 OAuth2 authentication with automatic token refresh
  • 🧩 Typed request/response models (generated with json_serializable)
  • 🗂️ Repository-per-domain API (athletes, activities, segments, …)
  • ⚠️ Structured error handling via Fault
  • 📖 Bundled, validated OpenAPI specs for the Strava API

Looking for a hands-on tour? The example app is an interactive API explorer that lets you log in and run every call against your account.

Table of contents #

Installation #

Add the package:

flutter pub add strava_client

or in pubspec.yaml:

dependencies:
  strava_client: ^2.3.0

Requires Dart >=3.8.0.

Quick start #

import 'package:strava_client/strava_client.dart';

final stravaClient = StravaClient(
  clientId: "YOUR_CLIENT_ID",
  secret: "YOUR_CLIENT_SECRET",
);

Future<void> main() async {
  // 1. Authenticate (opens the Strava login / consent screen).
  final token = await stravaClient.authentication.authenticate(
    scopes: [
      AuthenticationScope.profile_read_all,
      AuthenticationScope.read_all,
      AuthenticationScope.activity_read_all,
    ],
    redirectUrl: "stravaflutter://redirect",
    callbackUrlScheme: "stravaflutter",
  );
  print("Access token: ${token.accessToken}");

  // 2. Call the API — the token is attached (and refreshed) automatically.
  final athlete = await stravaClient.athletes.getAuthenticatedAthlete();
  print("Hello ${athlete.firstname}!");
}

Create the client once and reuse it (it wires up shared session state).

Platform setup #

The redirect URL scheme used in the snippets below is stravaflutter://redirect. In your Strava API settings set the Authorization Callback Domain to redirect.

Android #

Add the callback activity to android/app/src/main/AndroidManifest.xml:

<activity
    android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
    android:exported="true">
    <intent-filter android:label="flutter_web_auth_2">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:host="redirect" android:scheme="stravaflutter" />
    </intent-filter>
</activity>

Set android:launchMode="singleTop" on your main activity and remove any android:taskAffinity entries.

On Android 9 (API 28) the auth webview can throw net::ERR_CLEARTEXT_NOT_PERMITTED. If so, add android:usesCleartextTraffic="true" to your <application> tag.

iOS #

Add the URL scheme to ios/Runner/Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>stravaflutter</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>stravaflutter</string>
        </array>
    </dict>
</array>

To let users authenticate through the native Strava app when installed, also add:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>strava</string>
</array>

The web platform is not supported (the OAuth redirect does not return to the app). Use Android or iOS.

Authentication #

// Authenticate. If a valid token is already stored it is reused; an expired
// token is refreshed automatically.
final TokenResponse token = await stravaClient.authentication.authenticate(
  scopes: [AuthenticationScope.activity_read_all],
  redirectUrl: "stravaflutter://redirect",
  callbackUrlScheme: "stravaflutter",
  forceShowingApproval: false, // force the consent screen even if already granted
  preferEphemeral: true,       // iOS: don't share cookies with Safari
);

// Revoke access and clear the stored token.
await stravaClient.authentication.deAuthorize();

Available scopes (AuthenticationScope): read, read_all, profile_read_all, profile_write, activity_read, activity_read_all, activity_write.

Token storage & refresh #

Tokens are persisted with shared_preferences and reused across launches. On every authenticated request the client checks expiry and transparently refreshes the access token using the stored refresh token, so you don't have to manage refresh yourself.

Making API calls #

Calls are grouped into repositories on the client:

Getter Repository
stravaClient.authentication OAuth
stravaClient.athletes Athlete
stravaClient.activities Activities
stravaClient.clubs Clubs
stravaClient.gears Gear
stravaClient.routes Routes
stravaClient.runningRaces Running races
stravaClient.segments Segments
stravaClient.segmentEfforts Segment efforts
stravaClient.streams Streams
stravaClient.uploads Uploads
// Recent activities
final activities = await stravaClient.activities.listLoggedInAthleteActivities(
  DateTime.now(),                              // before
  DateTime.now().subtract(Duration(days: 30)), // after
  1,                                           // page
  30,                                          // per page
);

// A detailed segment
final segment = await stravaClient.segments.getSegment(229781);

// Activity streams keyed by type
final streams = await stravaClient.streams.getActivityStreamsByType(
  12345678,
  ["distance", "heartrate", "watts"],
);

Error handling #

Failed requests throw a typed Fault:

try {
  await stravaClient.athletes.getAuthenticatedAthlete();
} on Fault catch (fault) {
  print("message: ${fault.message}");
  for (final e in fault.errors ?? []) {
    print("  ${e.resource}.${e.field}: ${e.code}");
  }
}

Supported endpoints #

Athlete
  • getAuthenticatedAthlete
  • getAthleteZones (heart-rate & power zones)
  • getAthleteStats
  • updateAthlete
Activities
  • getActivity
  • listLoggedInAthleteActivities
  • listActivityComments
  • listActivityKudoers
  • getLapsByActivityId
  • getActivityZones
  • createActivity
  • updateActivity
Clubs
  • getClub
  • getLoggedInAthleteClubs
  • listClubActivities
  • listClubAdministrators
  • listClubMembers
Gear / Routes / Running races
  • gears.getGearById
  • routes.getRoute, routes.listAthleteRoutes, routes.exportRouteGPX, routes.exportRouteTCX
  • runningRaces.listRunningRaces, runningRaces.getRage
Segments & efforts
  • segments.getSegment
  • segments.listStarredSegments
  • segments.exploreSegments
  • segments.getLeaderBoard
  • segments.starSegment
  • segmentEfforts.getSegmentEffort, segmentEfforts.listSegmentEfforts
Streams & uploads
  • streams.getActivityStreams / getActivityStreamsByType
  • streams.getRouteStreams / getRouteStreamsByType
  • streams.getSegmentStreams / getSegmentStreamsByType
  • streams.getSegmentEffortStreams / getSegmentEffortStreamsByType
  • uploads.uploadActivity, uploads.getUpload

To upload activities you can generate TCX files with the rw_tcx package.

Missing an endpoint? Open an issue or send a PR — the repository pattern makes new calls easy to add.

Example app #

The example/ directory is a full API Explorer: log in with OAuth, pick any call from a grouped list, fill in its parameters, and see the pretty-printed JSON response (or Fault).

cd example
cp lib/secret.dart.example lib/secret.dart   # add your clientId + secret
flutter run

Contributing #

Contributions are welcome! Please:

  1. Open an issue for bugs or feature requests.
  2. For PRs: keep changes backwards compatible where possible, run dart analyze and flutter test, and add tests where it makes sense.

CI runs analysis and tests on every PR.

Acknowledgements #

  • @Birdyf for the original package.
  • Patrick Finkelstein, the package's original maintainer.
  • Joe Birch — OAuth reference.
  • Strava's published Swagger spec, bundled and validated under openapi/.

License #

MIT — Copyright (c) 2019-present Serdar Coşkun and contributors.

13
likes
160
points
1.23k
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

An unofficial Flutter client for the Strava V3 API: OAuth2 authentication with automatic token refresh, typed models, and repository-based endpoints.

Repository (GitHub)
View/report issues

Topics

#strava #fitness #oauth #http #api

License

MIT (license)

Dependencies

app_links, dio, flutter, flutter_web_auth_2, get_it, json_annotation, shared_preferences, url_launcher

More

Packages that depend on strava_client