Strava Ruby Client

Gem Version Build Status

A complete Ruby client for the Strava API v3.

Unlike other clients, including strava-api-v3, provides complete OAuth refresh token flow support, webhooks support, a richer first class interface to Strava models, conversion helpers for distance, time and elevation, natively supports pagination, implements more consistent error handling and is built with thorough test coverage using actual Strava data.

Table of Contents

Installation

Add to Gemfile.

gem 'strava-ruby-client'

Run bundle install.

Usage

Use an access token obtained from My API Application in the Strava UI, the strava-oauth-token tool or the OAuth Workflow in your application.

client = Strava::Api::Client.new(
  access_token: "12345678987654321"
)

Activities

Create an Activity

Creates a manual activity for an athlete.

activity = client.create_activity(
  name: 'Afternoon Run',
  type: 'Run',
  start_date_local: Time.now,
  elapsed_time: 1234, # in seconds
  description: 'Test run.',
  distance: 1000 # in meters
)

activity.name # => 'Afternoon Run'
activity.strava_url # => 'https://www.strava.com/activities/1982980795'

See Strava::Models::Activity for all available properties.

Get Activity

Returns the given activity that is owned by the authenticated athlete.

activity = client.activity(1982980795)

activity.name # => 'Afternoon Run'
activity.strava_url # => 'https://www.strava.com/activities/1982980795'

See Strava::Models::Activity for all available properties.

Use map.summary_polyline and combine with polylines to parse the activity map and to construct a Google maps URL with start and end markers.

map = activity.map # => Strava::Models::Map

decoded_summary_polyline = Polylines::Decoder.decode_polyline(map.summary_polyline)
start_latlng = decoded_summary_polyline[0]
end_latlng = decoded_summary_polyline[-1]

google_maps_api_key = ENV['GOOGLE_STATIC_MAPS_API_KEY']

google_image_url = "https://maps.googleapis.com/maps/api/staticmap?maptype=roadmap&path=enc:#{map.summary_polyline}&key=#{google_maps_api_key}&size=800x800&markers=color:yellow|label:S|#{start_latlng[0]},#{start_latlng[1]}&markers=color:green|label:F|#{end_latlng[0]},#{end_latlng[1]}"

See Strava::Models::Map for all available properties.

List Activity Photos

Returns the photos on the given activity. This API is undocumented.

photos = client.activity_photos(1982980795) # => Array[Strava::Models::Photo]

photo = photos.first # => Strava::Models::Photo

photo.id # => nil
photo.unique_id # => '65889142-538D-4EE5-96F5-3DC3B773B1E3'
photo.urls # => { '0' => 'https://dgtzuqphqg23d.cloudfront.net/eb4DMJ2hJW3k_g9URZEMfaJ8rZfHagrNlZRuEZz0osU-29x64.jpg' }
photo.athlete_id # => 26_462_176
photo.activity_id # => 1_946_417_534
photo.activity_name # => 'TCS NYC Marathon 2018'
photo.created_at # => Time
photo.uploaded_at # => Time
photo.sizes # => { '0' => [29, 64] }
photo.default_photo # => false

See Strava::Models::Photo for all available properties.

List Activity Comments

Returns the comments on the given activity.

comments = client.activity_comments(1982980795) # => Array[Strava::Models::Comment]

comment = comments.first # => Strava::Models::Comment

comment.text # => 'Молодчина!'
comment.athlete.username # => 'zolotov'

See Strava::Models::Comment for all available properties.

List Activity Kudoers

Returns the athletes who kudoed an activity identified by an identifier.

kudoers = client.activity_kudos(1982980795) # => Array[Strava::Models::Athlete]

kodoer = kudoers.first # => Strava::Models::Athlete

kudoer.username # => 'zolotov'

See Strava::Models::Athlete for all available properties.

List Activity Laps

Returns the laps of an activity identified by an identifier.

laps = client.activity_laps(1982980795) # => Array[Strava::Models::Lap]

lap = laps.first # => Strava::Models::Lap

lap.name # => 'Lap 1'

See Strava::Models::Lap for all available properties.

List Athlete Activities

Returns the currently logged-in athlete's activities.

activities = client.athlete_activities # => Array[Strava::Models::Activity]

activity = activities.first # => Strava::Models::Activity

activity.name # => 'NYC TCS Marathon 2018'
activity.strava_url # => 'https://www.strava.com/activities/1477353766'
activity.type_emoji # => '🏃'
activity.distance_s # => '42.2km'
activity.moving_time_in_hours_s # => '3h38m5s'
activity.elapsed_time_in_hours_s # => '3h42m13s'
activity.pace_s # => '5m15s/km'
activity.pace_per_mile_s # => '8m28s/mi'
activity.speed_s # => '11.4km/h'
activity.miles_per_hour_s # => '7.1mph'
activity.total_elevation_gain_s # => '270.9m'
activity.total_elevation_gain_in_feet_s # => '888.8ft'

See Strava::Models::Activity, Strava::Models::Mixins::Distance, Strava::Models::Mixins::Elevation and Strava::Models::Mixins::Time for all available properties.

Get Activity Zones

Returns the zones of a given activity.

zones = client.activity_zones(1982980795) # => Array[Strava::Models::ActivityZone]

zone = zones.first # => Strava::Models::ActivityZone
zones.type # => 'heartrate'

distribution_buckets = activity_zone.distribution_buckets # => Array[Strava::Models::TimedZoneRange]

distribution_bucket = distribution_buckets.first # => Strava::Models::TimedZoneRange

distribution_bucket.min # => 0
distribution_bucket.max # => 123
distribution_bucket.time # => 20

See Strava::Models::ActivityZone and Strava::Models::TimedZoneRange for all available properties.

Update Activity

Update an activity.

activity = client.update_activity(
  id: 1982980795,
  name: 'Afternoon Run (Updated)',
  type: 'Run',
  description: 'It was cold.'
)

activity.name # => 'Afternoon Run (Updated)'
activity.strava_url # => 'https://www.strava.com/activities/1982980795'

Athletes

Get Authenticated Athlete

Returns the currently authenticated athlete.

client.athlete # => Strava::Models::Athlete

See Strava::Models::Athlete for all available properties.

Get Zones

Returns the the authenticated athlete's heart rate and power zones.

athlete_zones = client.athlete_zones # => Strava::Models::Zones

heart_rate = athlete_zones.heart_rate # => Strava::Models::HeartRateZoneRanges
heart_rate.custom_zone # => false

zone = heart_rate.zones.first # => Strava::Models::ZoneRange
zone.min # => 0
zone.max # => 123

See Strava::Models::Zones, Strava::Models::HeartRateZoneRanges, Strava::Models::PowerZoneRanges and Strava::Models::ZoneRange for all available properties.

Get Athlete Stats

Returns the activity stats of an athlete.

athlete_stats = client.athlete_stats(26462176) # => Strava::Models::ActivityStats

recent_run_totals = athlete_stats.recent_ride_totals # => Strava::Models::ActivityTotal

recent_run_totals.count # => 7
recent_run_totals.distance # => 78049.90087890625
recent_run_totals.distance_s # => '78.05km'
recent_run_totals.moving_time # => 25647
recent_run_totals.moving_time_in_hours_s # => '7h7m27s'
recent_run_totals.elapsed_time # => 26952
recent_run_totals.elapsed_time_in_hours_s # => '7h29m12s'
recent_run_totals.elevation_gain # => 595.4644241333008
recent_run_totals.total_elevation_gain_s # => '595.5m'
recent_run_totals.achievement_count # => 19

See Strava::Models::ActivityStats and Strava::Models::ActivityTotal for all available properties.

Update Athlete

Update the currently authenticated athlete.

athlete = client.update_athlete(weight: 90.1) # => Strava::Models::Athlete

See Strava::Models::Athlete for all available returned properties.

Clubs

List Club Activities

Retrieve recent activities from members of a specific club.

activities = client.club_activities(108605) # => Array[Strava::Models::Activity]

activity = activities.first # => Strava::Models::Activity

activity.name # => 'Afternoon Run'

See Strava::Models::Activity for all available properties. Note that Strava does not return activity or athlete ID via this API.

List Club Administrators

Returns a list of the administrators of a given club.

admins = client.club_admins(108605) # => Array[Strava::Models::ClubAdmin]

admin = admins.first # => Strava::Models::ClubAdmin
admin.name # => 'Peter Ciaccia'

See Strava::Models::ClubAdmin for all available properties.

Get Club

Returns a given club using its identifier.

club = client.club(108605) # => Strava::Models::Club

club.name # => 'NYRR'

See Strava::Models::Club for all available properties.

List Club Members

Returns a list of the members of a given club.

members = client.club_members(108605) # => Array[Strava::Models::ClubMember]

member = members.first # => Strava::Models::ClubMember
member.name # => 'Peter Ciaccia'

See Strava::Models::ClubMember for all available properties.

List Athlete Clubs

Returns a list of the clubs whose membership includes the authenticated athlete.

clubs = client.athlete_clubs # => Array[Strava::Models::Club]

club = clubs.first # => Strava::Models::Club

activity.name # => 'NYRR'
activity.strava_url # => 'https://www.strava.com/clubs/nyrr'

See Strava::Models::Club for all available properties.

Gears

Get Equipment

Returns an equipment using its identifier.

gear = client.gear('g3844087') # => Strava::Models::Gear

gear.id # => 'g3844087'
gear.name # => 'Adidas Supernova ST'
gear.distance # => 380939.0
gear.distance_s # => '380.94km'
gear.brand_name # => 'Adidas'
gear.model_name # => 'Supernova'
gear.description # => 'My NYC TCS Marathon 2018 shoes.'

See Strava::Models::Gear for all available properties.

Routes

Export Route GPX

Returns GPS Exchange Format (GPX) data of the route. Combine with multi_xml or gpx to parse it.

data = client.export_route_gpx(16341573) # => String

require 'multi_xml'
xml = MultiXml.parse(data) # => parsed GPX

require 'gpx'
gpx = GPX::GPXFile.new(gpx_data: data) # => GPX::GPXFile

gpx.name # => 'Lower Manhattan Loop'
gpx.description # => 'My usual long run when I am too lazy to go to Central Park.'
gpx.tracks # => Array[GPX::Track]

Export Route TCX

Returns a Training Center XML (TCX) data of the route. Combine with multi_xml to parse it.

data = client.export_route_tcx(16341573) # => String

require 'multi_xml'
xml = MultiXml.parse(data) # => parsed TCX

Get Route

Returns a route using its identifier.

route = client.route(16341573) # => Strava::Models::Route

route.name # => 'Lower Manhattan Loop'
route.description # => 'My usual long run when I am too lazy to go to Central Park.'

See Strava::Models::Route for all available properties.

List Athlete Routes

Returns a list of the routes by athlete ID.

routes = client.athlete_routes(26462176) # => Array[Strava::Models::Route]

route = routes.first # => Strava::Models::Route

route.name # => 'Lower Manhattan Loop'
route.description # => 'My usual long run when I am too lazy to go to Central Park.'
route.moving_time_in_hours_s # => '1h21m5s'

See Strava::Models::Route for all available properties.

Running Races

Get Running Race

Returns a running race for a given identifier.

running_race = client.running_race(1577) # => Strava::Models::RunningRace

running_race.name # => 'Walt Disney World Marathon 10k'
running_race.distance # => 10_000.0
running_race.distance_s # => '10km'
running_race.city # => 'Orlando'
running_race.state # => 'FL'
running_race.country # => 'United States'
running_race.strava_url # => 'https://www.strava.com/running-races/2018-walt-disney-world-marathon-10k'
running_race.website_url # => 'https://www.rundisney.com/disneyworld-marathon/'

See Strava::Models::RunningRace for all available properties.

List Running Races

Returns a list running races based on a set of search criteria.

running_races = client.running_races

running_race = running_races.first # => Strava::Models::RunningRace

running_race.name # => 'Walt Disney World Half Marathon'
running_race.distance # => 21_097.0
running_race.measurement_preference # => 'feet'
running_race.distance_s # => '13.11mi'

See Strava::Models::RunningRace for all available properties.

Segment Efforts

List Segment Efforts

Returns a set of the authenticated athlete's segment efforts for a given segment.

segment_efforts = client.segment_efforts(1109718)

segment_effort = segment_efforts.first # => Strava::Models::SegmentEffort

segment_effort.name # => 'E 14th St Climb'
segment_effort.activity # => Strava::Models::Activity
segment_effort.athlete # => Strava::Models::Athlete
segment_effort.elapsed_time # => 116
segment_effort.distance # => 398.6
segment_effort.distance_s # => '0.4km'
segment_effort.average_heartrate # => 152.2
segment_effort.max_heartrate # => 158.0

segment_effort.achievements # => Enumerable

achievement = segment_effort.achievements.first # => Strava::Models::Achievement
achievement.rank # => 1
achievement.type # => 'pr'
achievement.type_id # => 3

See Strava::Models::SegmentEffort and Strava::Models::Achievement for all available properties.

Get Segment Effort

Returns a segment effort from an activity that is owned by the authenticated athlete.

segment_effort = client.segment_effort(41494197089) # => Strava::Models::SegmentEffort

segment_effort.name # => 'E 14th St Climb'
segment_effort.activity # => Strava::Models::Activity
segment_effort.elapsed_time # => 116

segment_stats = segment_effort.athlete_segment_stats # => Strava::Models::SegmentStats
segment_stats.pr_elapsed_time # => 116
segment_stats.elapsed_time_in_hours_s # => '1m56s'
segment_stats.pr_date # => Date
segment_stats.effort_count # => 3

See Strava::Models::SegmentEffort and Strava::Models::SegmentStats for all available properties.

Segments

Explore Segments

Returns the top 10 segments matching a specified query.

segments = client.explore_segments(bounds: [36.372975, -94.220234, 36.415949, -94.183670], activity_type: 'running')

segment = segments.first # => Strava::Models::ExplorerSegment
segment.name # => 'Compton Gardens hill'
segment.avg_grade # => 4.6
segment.start_latlng # => [36.377702, -94.207242]
segment.end_latlng # => [36.375948, -94.207689]
segment.elev_difference # => 9.6

See Strava::Models::ExplorerSegment for all available properties.

Get Segment Leaderboard

Returns the specified segment leaderboard.

segment_leaderboard = client.segment_leaderboard(1109718) # => Strava::Models::SegmentLeaderboard

segment_leaderboard.effort_count # => 204
segment_leaderboard.entry_count # => 204
segment_leaderboard.kom_type # => 'kom'
segment_leaderboard.entries # => Enumerable

entry = segment_leaderboard.entries.first # => Strava::Models::SegmentLeaderboardEntry
entry.athlete_name # => 'Etan B.'
entry.moving_time_in_hours_s # => '1m32s'
entry.start_date # => Time
entry.start_date_local # => Time
entry.rank # => 1

This API supports pagination through the entire segment leaderboard but wraps entries into a Strava::Models::SegmentLeaderboard object.

client.segment_leaderboard(1109718) do |row|
  row # => Strava::Models::SegmentLeaderboard
  row.entries # => Array[Strava::Models::SegmentLeaderboardEntry]
end

See Strava::Models::SegmentLeaderboard and Strava::Models::SegmentLeaderboardEntry for all available properties.

List Starred Segments

List of the authenticated athlete's starred segments.

segments = client.starred_segments

segment = segments.first # => Strava::Models::Segment

segment.pr_time # => 256
segment.elapsed_time_in_hours_s # => '4m16s'
segment.starred_date # => Time
segment.athlete_pr_effort # => Strava::Models::SegmentEffort

See Strava::Models::Segment and Strava::Models::SegmentEffort for all available properties.

Get Segment

Returns the specified segment.

segment = client.segment(1109718) # => Strava::Models::Segment

segment.name # => 'E 14th St Climb'
segment.city # => 'New York'
segment.state # => 'NY'
segment.country # => 'United States'
segment.map # => Strava::Models::Map
segment.effort_count # => 750
segment.athlete_count # => 206
segment.star_count # => 1
segment.athlete_segment_stats # => Strava::Models::SegmentStats

See Strava::Models::Segment for all available properties.

Star Segment

Stars/unstars the given segment for the authenticated athlete.

segment = client.star_segment(50272077110, starred: true) # => Strava::Models::Segment

segment.name # => 'E 14th St Climb'
segment.starred # => true

See Strava::Models::Segment for all available properties.

Streams

Stream APIs can return various streams by key(s).

streams = client.segment_streams(1109718, keys: %w[distance latlng altitude]) # => Strava::Models::StrewamSet

streams.distance # => Strava::Models::Stream
streams.latlng # => Strava::Models::Stream
streams.altitude # => Strava::Models::Stream

Get Activity Streams

Returns the given activity's streams.

streams = client.activity_streams(1946417534) # => Strava::Models::StreamSet

distance = streams.distance # => Strava::Models::Stream
distance.original_size # => 13_129
distance.resolution # => 'high'
distance.series_type # => 'distance'
distance.data # => Array[Float]

See Strava::Models::StreamSet and Strava::Models::Stream for all available properties.

Get Segment Effort Streams

Returns a set of streams for a segment effort completed by the authenticated athlete.

streams = client.segment_effort_streams(41494197089)

distance = streams.distance # => Strava::Models::Stream
distance.original_size # => 117
distance.resolution # => 'high'
distance.series_type # => 'distance'
distance.data # => Array[Float]

See Strava::Models::StreamSet and Strava::Models::Stream for all available properties.

Get Segment Streams

Returns the given segment's streams.

streams = client.segment_streams(1109718) # => Strava::Models::StreamSet

distance = streams.distance # => Strava::Models::Stream
distance.original_size # => 32
distance.resolution # => 'high'
distance.series_type # => 'distance'
distance.data # => Array[Float]

See Strava::Models::StreamSet and Strava::Models::Stream for all available properties.

Uploads

Upload Activity

Uploads a new data file to create an activity from.

upload = client.create_upload(
  file: Faraday::UploadIO.new('17611540601.tcx', 'application/tcx+xml'),
  name: 'Uploaded Activity',
  description: 'Uploaded by strava-ruby-client.',
  data_type: 'tcx',
  external_id: 'strava-ruby-client-upload-1'
) # => Strava::Models::Upload

upload.id # => 2136460097
upload.external_id # => 'strava-ruby-client-upload-1.tcx'
upload.error # => nil
upload.status # => 'Your activity is still being processed.'
upload.activity_id # => nil

See Strava::Models::Upload for all available properties.

Get Upload

Returns an upload for a given identifier.

upload = client.upload(2136460097) # => Strava::Models::Upload

upload.id # => 2_136_460_097
upload.external_id # => 'strava-ruby-client-upload-1.tcx'
upload.error # => nil
upload.status # => 'Your activity is ready.'
upload.activity_id # => 1_998_557_443

See Strava::Models::Upload for all available properties.

Pagination

Some Strava APIs, including athlete-activities support pagination when supplying an optional page and per_page parameter. By default the client retrieves one page of data, which Strava currently defaults to 30 items. You can paginate through more data by supplying a block and an optional per_page parameter. The underlying implementation makes page-sized calls and increments the page argument.

client.athlete_activities(per_page: 30) do |activity|
  activity # => Strava::Models::Activity
end

OAuth

OAuth Workflow

Obtain a redirect URL using an instance of Strava::OAuth::Client.

client = Strava::OAuth::Client.new(
  client_id: "12345",
  client_secret: "12345678987654321"
)

redirect_url = client.authorize_url(
  redirect_uri: 'https://example.com/oauth',
  approval_prompt: 'force',
  response_type: 'code',
  scope: 'activity:read_all',
  state: 'magic'
)

Once the user is redirected to your application, perform a token exchange to obtain a refresh and access token.

response = client.oauth_token(code: '1234556789901234567890')

response # => Strava::Models::Token

response.access_token # access token
response.refresh_token # refresh token
response.expires_at # timestamp when the access token expires
response.athlete # => Strava::Models::Athlete

See Strava authentication documentation, Strava::Models::Token and Strava::Models::Athlete for all available properties in the response.

If the access token is expired, refresh it before making any requests. You will get back all new tokens.

response = client.oauth_token(
  refresh_token: '...',
  grant_type: 'refresh_token'
)

response.access_token # => String, new access token
response.refresh_token # => String, new refresh token
response.expires_at # => Time, new timestamp when the access token expires

Deauthorize

Revoke access to an athlete's data using an instance of Strava::API::Client.

authorization = client.deauthorize

authorization.access_token # => String, access token being revoked

Command Line OAuth Workflow

The OAuth process is web-based and you cannot obtain a token from a Strava client ID and secret without user intervention. You can, however, start a local web server to handle the OAuth redirect and open a browser from the command-line.

See strava-oauth-token or strava-ruby-cli for an example.

Webhooks

Strava provides a Webhook Event API.

A complete example that handles subscription creation, deletion and handling can be found in strava-webhooks. Run strava-webhooks to see current registrations, strava-webhooks handle to run an HTTP server that handles both challenges and event data, strava-webhooks create [url] to create a new subscription and strava-webhooks delete [id] to delete it.

Before creating a webhook subscription you must implement and run an HTTP server that will handle a GET challenge at the subscription URL.

challenge = Strava::Webhooks::Models::Challenge.new(request.query)
raise 'Bad Request' unless challenge.verify_token == 'token'
response.content_type = 'application/json'
response.body = challenge.response.to_json

See Strava::Webhooks::Models::Challenge for details.

An existing subscription must be handled in the same HTTP server's POST request to the subscription URL.

event = Strava::Webhooks::Models::Event.new(JSON.parse(request.body))

event # => Strava::Webhooks::Models::Event
event.object_type # => 'activity'
event.object_id # => 1991813808
event.aspect_type # => 'update'
event.updates # => { 'type' => 'Walk' }
event.owner_id # => 29323238
event.subscription_id # => 131302
event.event_time # => DateTime

See Strava::Webhooks::Models::Event for details.

Subscriptions can be created, listed and deleted.

Create a client.

client = Strava::Webhooks::Client.new(
  client_id: "12345",
  client_secret: "12345678987654321"
)

Create a subscription.

subscription = client.create_push_subscription(callback_url: 'http://example.com/strava', verify_token: 'token')

subscription # => Strava::Webhooks::Models::Subscription
subscription.id # => 131300
subscription.callback_url # => 'http://example.com/strava'

See Strava::Webhooks::Models::Subscription for details.

List an existing subscription. Strava seems to only allow one.

subscriptions = client.push_subscriptions

subscription = subscriptions.first # => Strava::Webhooks::Models::Subscription
subscription.id # => 131300
subscription.callback_url # => 'http://example.com/strava'

Delete an existing subscription.

client.delete_push_subscription(131300) # => nil

Configuration

Web Client Options

You can configure web client options used in the OAuth and API clients, globally.

Strava::Web::Client.configure do |config|
  config.user_agent = 'Strava Ruby Client/1.0'
end

The following settings are supported.

setting description
user_agent User-agent, defaults to Strava Ruby Client/version.
proxy Optional HTTP proxy.
ca_path Optional SSL certificates path.
ca_file Optional SSL certificates file.
logger Optional Logger instance that logs HTTP requests.
timeout Optional open/read timeout in seconds.
open_timeout Optional connection open timeout in seconds.

API Client Options

The API client inherits web client options and provides additional application configuration. These can be configured globally or for a client instance.

Strava::API.configure do |config|
  config.access_token = "..." # Strava access token
end
client = Strava::API::Client.new(
  access_token: "...",
  user_agent: "..."
)

The following settings are supported.

setting description
access_token Access token to pass in the Authorization header.
endpoint Defaults to https://www.strava.com/api/v3.

OAuth Client Options

The OAuth client inherits web client options and provides additional application configuration. These can be configured globally or for a client instance.

Strava::OAuth.configure do |config|
  config.client_id = "..." # Strava client ID
  config.client_secret = "..." # Strava client secret
end
client = Strava::OAuth::Client.new(
  client_id: "...",
  client_secret: "...",
  user_agent: "..."
)

The following settings are supported.

setting description
client_id Application client ID.
client_secret Application client secret.
endpoint Defaults to https://www.strava.com/oauth.

Webhooks Client Options

The Webhooks client inherits web client options and provides additional application configuration. These can be configured globally or for a client instance.

Strava::Webhooks.configure do |config|
  config.client_id = "..." # Strava client ID
  config.client_secret = "..." # Strava client secret
end
client = Strava::Webhooks::Client.new(
  client_id: "...",
  client_secret: "...",
  user_agent: "..."
)

The following settings are supported.

setting description
client_id Application client ID.
client_secret Application client secret.
endpoint Defaults to https://www.strava.com/api/v3.

Errors

All errors that return HTTP codes 400-600 result in either Faraday::ResourceNotFound, Faraday::ConnectionFailed or Strava::Errors::Fault exceptions.

begin
  client.oauth_token(code: 'invalid')
rescue Strava::Errors::Fault => e
  e.message # => Bad Request
  e.errors # => [{ 'code' => 'invalid', 'field' => 'code', 'resource' => 'RequestToken' }]
  e.headers # => { "status" => "403 Bad Request", "x-ratelimit-limit" => "600,30000", "x-ratelimit-usage" => "314,27536" }
end

Tools

For a complete set of command-line tools, check out strava-ruby-cli built on top of this gem.

Strava OAuth Token

Use strava-oauth-token to obtain a token from the command-line. This will open a new browser window, navigate to Strava, request the appropriate permissions, then handle OAuth in a local redirect. The token type, refresh token, access token and token expiration will be displayed in the browser.

$ STRAVA_CLIENT_ID=... STRAVA_CLIENT_SECRET=... strava-oauth-token

Users

Resources

Upgrading

See UPGRADING.

Contributing

See CONTRIBUTING.

Copyright (c) 2018, Daniel Doubrovkine and Contributors.

This project is licensed under the MIT License.