{"id":16192940,"url":"https://github.com/slashdotdash/strava","last_synced_at":"2025-04-24T00:23:46.428Z","repository":{"id":4366878,"uuid":"49909737","full_name":"slashdotdash/strava","owner":"slashdotdash","description":"Elixir wrapper for the Strava API (v3)","archived":false,"fork":false,"pushed_at":"2024-05-09T11:21:16.000Z","size":526,"stargazers_count":48,"open_issues_count":7,"forks_count":17,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-19T07:24:07.014Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slashdotdash.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-18T22:30:14.000Z","updated_at":"2024-10-26T16:04:36.000Z","dependencies_parsed_at":"2024-11-09T18:00:39.699Z","dependency_job_id":"cf1abe35-edd4-4e61-8076-c60001d80d9c","html_url":"https://github.com/slashdotdash/strava","commit_stats":{"total_commits":92,"total_committers":11,"mean_commits":8.363636363636363,"dds":0.3152173913043478,"last_synced_commit":"1980b6ca9386bc4273b55a784a4f57058bd5037e"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdotdash%2Fstrava","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdotdash%2Fstrava/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdotdash%2Fstrava/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slashdotdash%2Fstrava/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slashdotdash","download_url":"https://codeload.github.com/slashdotdash/strava/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250536483,"owners_count":21446743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T08:13:24.317Z","updated_at":"2025-04-24T00:23:46.409Z","avatar_url":"https://github.com/slashdotdash.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Strava\n\nElixir wrapper for the [Strava API](https://developers.strava.com/) (v3), generated from the official [Strava API Swagger definition](https://developers.strava.com/docs/#client-code) using the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator).\n\nAll calls to the Strava API require an `access_token` defining the athlete and application making the call. Any registered Strava user can create their own application at [developers.strava.com](https://developers.strava.com/).\n\n---\n\n[Changelog](CHANGELOG.md)\n\nMIT License\n\n[![Build Status](https://travis-ci.org/slashdotdash/strava.svg?branch=master)](https://travis-ci.org/slashdotdash/strava)\n\n---\n\n\u003e This README and the following guides follow the `master` branch which may not be the currently published version.\n\u003e [Read docs for the latest published version of Strava on Hex](https://hexdocs.pm/strava/).\n\n## Installation\n\n  1. Add `strava` to your list of dependencies in `mix.exs`:\n\n  ```elixir\n  def deps do\n    [{:strava, \"~\u003e 1.0\"}]\n  end\n  ```\n\n## Usage\n\nAdd the following `strava` configuration settings to each environment's mix config file.\n\nEnter your Strava application settings as shown on https://www.strava.com/settings/api.\n\n```elixir\n# config/dev.exs\nuse Mix.Config\n\nconfig :strava,\n  client_id: \u003cclient id\u003e,\n  client_secret: \"\u003cclient secret\u003e\",\n  access_token: \"\u003caccess token\u003e\",\n  redirect_uri: \"\u003credirect url\u003e\"\n```\n\n### Client\n\nAll requests to the Strava API require [authentication](https://developers.strava.com/docs/authentication/).\n\nCreate a client to make requests as your own application:\n\n```elixir\nclient = Strava.Client.new()\n```\n\nProvide an athlete's `access_token` to make requests on behalf of an authenticated athlete:\n\n```elixir\nclient = Strava.Client.new(\"\u003c\u003caccess_token\u003e\u003e\")\n```\n\n#### Refresh expired tokens\n\nAccess tokens expire six hours after they are created, so they must be refreshed in order for an application to continuing making authenticated requests on behalf of an athlete.\n\nYou can create a client with an optional refresh token, used to refresh an expired access token, and optional callback function invoked when the token is refreshed.\n\n```elixir\nclient = Strava.Client.new(\"\u003caccess_token\u003e\",\n  refresh_token: \"\u003crefresh_token\u003e\",\n  token_refreshed: fn client -\u003e IO.inspect(client, label: \"client\") end\n)\n```\n\nUsing the above client, whenever a \"401 Unauthorized\" HTTP response status code is returned from an API request an attempt will be made to refresh the token and retry the original request.\n\nThe `token_refreshed` callback function can be used to persist the refreshed `access_token` and `refresh_token` to be used for further requests for the athlete.\n\n### Clubs\n\n#### Get club by id\n\n```elixir\n{:ok, %Strava.DetailedClub{} = club} = Strava.Clubs.get_club_by_id(client, 1)\n```\n\n#### Get club members by id\n\n```elixir\n{:ok, members} = Strava.Clubs.get_club_members_by_id(client, 1, per_page: 20, page: 1)\n```\n\n### Segments\n\n#### Get segment by id\n\n```elixir\n{:ok, %Strava.DetailedSegment{}} = Strava.Segments.get_segment_by_id(client, 229781)\n```\n\n### Segment efforts\n\n#### Get efforts by segment id\n\n```elixir\n{:ok, segment_efforts} = Strava.SegmentEfforts.get_efforts_by_segment_id(client, 229781)\n```\n\nReturns segment efforts for the authenticated athlete only.\n\n##### Get efforts by start and end dates\n\n```elixir\n{:ok, segment_efforts} = Strava.SegmentEfforts.get_efforts_by_segment_id(client, 229781,\n  start_date_local: \"2014-01-01T00:00:00Z\",\n  end_date_local: \"2014-01-01T23:59:59Z\"\n})\n```\n\nConvert `DateTime` structs to an ISO 8601 formatted date time string using:\n\n```elixir\nDateTime.to_iso8601(start_date_local)\n```\n\n#### Get segment effort by id\n\n```elixir\n{:ok, %Strava.DetailedSegmentEffort{} = segment_effort} =\n  Strava.SegmentEfforts.get_segment_effort_by_id(client, 269990681)\n```\n\n### Activities\n\n#### Get activity by id\n\n```elixir\n{:ok, %Strava.DetailedActivity{} = activity} = Strava.Activities.get_activity_by_id(client, 746805584)\n```\n\n#### Get logged in athlete's activities\n\n```elixir\n{:ok, activities} = Strava.Activities.get_logged_in_athlete_activities(client, per_page: 50, page: 1)\n```\n\n#### Stream paginated requests\n\nAny requests which take optional pagination params (`per_page` and `page`) can be converted to an Elixir `Stream` by using `Strava.Paginator.stream/2`.\n\nThe first argument is a function which is provided the current pagination params to make the request to the Strava API.\n\n```elixir\nstream =\n  Strava.Paginator.stream(\n    fn pagination -\u003e\n      Strava.SegmentEfforts.get_efforts_by_segment_id(client, segment_id, pagination)\n    end,\n    per_page: 10\n  )\n\nsegment_efforts = stream |\u003e Stream.take(20) |\u003e Enum.to_list()\n```\n\nA `Strava.Paginator.RequestError` error will be raised if the request returns an error tagged tuple.\n\n### OAuth support\n\nYou can use Strava as an authentication provider with the OAuth2 strategy included in this library.\n\nUse `Strava.Auth.authorize_url!/1` to generate the Strava URL to redirect unauthenticated users to. After the user has successfully authenticated with Strava you can use `Strava.Auth.get_token!` to access their summary details and unique access token required to make authenticated requests on behalf of the user.\n\nInclude the [access scopes](http://developers.strava.com/docs/authentication/#request-access) your application requires as a comma delimited string (e.g. `\"activity:read_all,activity:write\"`). Applications should request only the scopes required for the application to function normally.\n\nAn example Phoenix authentication controller is shown below:\n\n```elixir\ndefmodule Example.AuthController do\n  use Example.Web, :controller\n\n  def index(conn, _params) do\n    redirect(conn, external: Strava.Auth.authorize_url!(scope: \"profile:read,activity:read\"))\n  end\n\n  def delete(conn, _params) do\n    conn\n    |\u003e configure_session(drop: true)\n    |\u003e redirect(to: \"/\")\n  end\n\n  @doc \"\"\"\n  This action is reached via `/auth/callback` and is the the callback URL that\n  Strava will redirect the user back to with a `code` that will be used to\n  request an access token. The access token will then be used to access\n  protected resources on behalf of the user.\n  \"\"\"\n  def callback(conn, %{\"code\" =\u003e code}) do\n    client = Strava.Auth.get_token!(code: code, grant_type: \"authorization_code\")\n    athlete = Strava.Auth.get_athlete!(client)\n\n    conn\n    |\u003e put_session(:current_athlete, athlete)\n    |\u003e put_session(:access_token, client.token.access_token)\n    |\u003e put_session(:refresh_token, client.token.refresh_token)\n    |\u003e redirect(to: \"/\")\n  end\nend\n```\n\nWith the `access_token` tracked against the user's session you can make requests to the Strava API on their behalf. Use `Strava.Client.new(access_token)` to create a client to use with each request for that user.\n\n#### Refresh expired access tokens\n\nAccess tokens expire six hours after they are created, so they must be refreshed in order for an application to continuing making authenticated requests on behalf of an athlete.\n\nUse the refresh token returned from the initial token exchange to obtain a fresh access token.\n\n```elixir\nclient = Strava.Auth.get_token!(grant_type: \"refresh_token\", refresh_token: \"\u003crefresh_token\u003e\")\n\naccess_token = client.token.access_token\nrefresh_token = client.token.refresh_token\n```\n\nBoth the `access_token` and `refresh_token` tokens will need to be stored to ensure authenticated requests can be made and the token can be later refreshed after expiry.\n\n## Testing\n\nTo run the entire test suite, create a file called `config/test.secret.exs` with the following:\n\n```elixir\n# config/test.secret.exs\nuse Mix.Config\n\nconfig :strava,\n  access_token: \"\u003caccess_token\u003e\",\n  test: [\n    athlete_id: \"\u003cathlete_id\u003e\",\n    club_id: \"\u003cclub_id\u003e\",\n    segment_id: \"\u003csegment_id\u003e\"\n  ]\n```\n\nReplace the above placeholders with values appropriate for your own Strava application and athlete profile: your own athlete id; a club id you are a member of; and a segment you have made at least one attempt at.\n\nTo run the test suite:\n\n```\n$ mix test\n```\n\n## Contributing\n\nPull requests to contribute new or improved features, and extend documentation are most welcome.\n\nPlease follow the existing coding conventions, or refer to the Elixir style guide.\n\nYou should include unit tests to cover any changes.\n\n### Contributors\n\n- [Dave Shah](https://github.com/daveshah)\n- [Eric Thomas](https://github.com/et)\n- [Kerry Buckley](https://github.com/kerryb)\n- [Mathieu Fosse](https://github.com/pointcom)\n- [Paweł Koniarski](https://github.com/lewapkon)\n- [Ross Kaffenberger](https://github.com/rossta)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslashdotdash%2Fstrava","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslashdotdash%2Fstrava","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslashdotdash%2Fstrava/lists"}