스트라바(Strava) API
※ 기본적인 스트라바 SDK 사용하기 위해 필요한 값 ( 사이트에서 계정 생성하고 Setting 필요 )
client_id: 클라이언트 아이디
client_secret: 클라이언트 암호키
access_token: 엑세스 토큰
refresh_token: 새로고침 토큰
+ access_token은 유효시간은 6시간이며, API통신할때 권한을 부여받은것만 응답 받을 수 있음.
준비과정 및 엑세스 토큰 발급
Strava 계정 생성 또는 로그인
여기 를 클릭 하여 로그인하거나 Strava 계정을 만드세요.
Strava 계정에서 새 앱 설정
로그인한 후, 여기 로 이동합니다 . 처음에는 브라우저에 주소를 수동으로 입력해야 하지만 그 이후에는 을 클릭하여 스트라바 웹사이트를 통해 그곳으로 이동할 수 있습니다.
Swagger 도구가 작동하려면 Strava 계정 의 설정 섹션으로 돌아갑니다.
필드에서 “developers.strava.com ”로 입력합니다.
위에 내용을 입력하고 생성 버튼을 클릭하면 아래와 같이 키들을 보여줍니다.
인증 토큰 Access Token 발급 방법
Strava OAuth API : Strava Developers API 바로가기
안드로이드와 IOS는 위 URL을 참고해서 개발하시면 됩니다.
(아래 방법들에 따라 각각 위에서 세팅한 승인 콜백 도메인을 수정해야합니다.)
ⓐ. Swagger API 사용
Strava API의 범위 는 사용자 데이터를 읽거나 변경하는 데 필요한 다양한 액세스 수준을 나타냅니다.
타사 앱의 개발자로서 우리는 Strava에 특정 사용자에 대해 부여할 권한을 결정합니다. 필요한 것을 요청합니다.
Swagger UI 에 접속해서 authorize를 클릭해서 client_id와 client_secret를 입력해줍니다.
(승인 콜백 도메인 : developers.strava.com)
비공개로 설정된 활동을 포함하여 내 모든 활동에 액세스하고 싶으므로 activity:read_all범위를 사용합니다.
이것을 통해 API를 호출할 수 있는 권한을 부여해서 로그인 하여 토큰을 발급받습니다.
상황에 따라 필요에 따라 권한을 가져옵니다.
위 사진과 같이 OAuth2 페이지로 리다이렉션이 되고, 승인을 클릭하여 연결 허용합니다.
정상적으로 토큰이 발급됩니다.
여기까지 스웨거로 엑세스 토큰 발급받는 방법이었습니다.
ⓑ. 스트라바 관리자 페이지에서 지급받은 Access Token으로 사용
내 API애플리케이션 페이지에서 엑세스토큰에 보면 “보기”버튼을 클릭하고 해당 토큰으로 postman으로 테스트도 가능합니다.
단, 필요한 권한이 있다면 다시 부여받아야 합니다.
ⓒ. 스트라바 OAuth API를 통해 사용
(승인 콜백 도메인 : localhost)
http://www.strava.com/oauth/authorize?client_id=11111&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=activity:read_all
client_id를 맞게 입력해서 브라우저로 접속해줍니다.
열리지 않는 패이지 리다이렉트되고 이때 URL을 보면 code 파라미터값을 가져옵니다.
아래와 같이 터미널로 요청합니다.
curl -X POST https://www.strava.com/oauth/token?client_id=[클라이언트 아아디 입력]&client_secret=[시크릿 코드 입력]&code=[위에서 받은 code입력]
응답 값
{
"token_type": "Bearer",
"expires_at": ,
"expires_in": ,
"refresh_token": "",
"access_token": "",
"athlete": {
"id": ,
"username": null,
"resource_state": 2,
"firstname": "",
"lastname": "",
"bio": null,
"city": null,
"state": null,
"country": null,
"sex": "M",
"premium": false,
"summit": false,
"created_at": "2022-02-15T01:08:43Z",
"updated_at": "2022-02-15T05:20:01Z",
"badge_type_id": 0,
"weight": 0,
"profile_medium": "https://lh3.googleusercontent.com/a/=s96-c",
"profile": "https://lh3.googleusercontent.com/a/=s96-c",
"friend": null,
"follower": null
}
}
위와 같이 응답을 받게되고 엑세스 토큰은 6시간 유효하고 refresh token은 유효시간이 없습니다.
refresh token으로 계속 access token을 새로 발급 받습니다.
Refresh Token으로 Access Token 얻기
API 호출 시 Refresh Token을 사용해서 Access Token을 얻어오는 과정입니다.
Request parmater에서 grant_type을 'refresh_token'으로 설정해야 합니다.
Refresh Token으로 Access Token 얻기
url 명령어
curl -X POST https://www.strava.com/oauth/token
-d client_id=YOUR_CLIENTID
-d client_secret=YOUR_CLIENTSECRET
-d refresh_token=TOKEN FROM SERVER
-d grant_type=refresh_token
현재 활동 내역
유저가 활동한 웹과 앱의 화면
현재 테스트를 위해 위와 같이 아이폰 “스트라바”앱을 설치해서 활동을 만들어 보았습니다.
유저가 활동한 화면 입니다.
API 테스트
응답에 대한 각각의 key의 설명은 아래 여기 에서 확인 가능합니다.
유저의 정보 가져오기
curl -X GET "https://www.strava.com/api/v3/athlete" -H "accept: application/json" -H "authorization: Bearer e7d66fb11112"
응답
{
"id": ,
"username": null,
"resource_state": 2,
"firstname": "",
"lastname": "",
"bio": null,
"city": null,
"state": null,
"country": null,
"sex": "M",
"premium": false,
"summit": false,
"created_at": "2022-02-15T01:08:43Z",
"updated_at": "2022-02-15T05:20:01Z",
"badge_type_id": 0,
"weight": 0.0,
"profile_medium": "https://lh3.googleusercontent.com/a/=s96-c",
"profile": "https://lh3.googleusercontent.com/a/=s96-c",
"friend": null,
"follower": null
}
선수 활동 나열 (list)
특정 식별자에 대한 운동선수(유저)의 활동을 반환합니다.
activity:read_all의 권한이 필요합니다.
Swagger 바로가기 에서 테스트를 해봐도 되고, 아래와 같이 터미널에서 확인해봐도 됩니다.
request
curl -X GET "https://www.strava.com/api/v3/athlete/activities?per_page=30" -H "accept: application/json" -H "authorization: Bearer e71f1ad1a14d646fb3ec0712"
response
[
{
"resource_state": 2,
"athlete": {
"id": ,
"resource_state": 1
},
"name": "첫번째 달리기 테스트트2",
"distance": 754.8,
"moving_time": 155,
"elapsed_time": 161,
"total_elevation_gain": 0,
"type": "Run",
"workout_type": 3,
"id": ,
"start_date": "2022-02-15T05:16:12Z",
"start_date_local": "2022-02-15T14:16:12Z",
"timezone": "(GMT+09:00) Asia/Seoul",
"utc_offset": 32400,
"location_city": null,
"location_state": null,
"location_country": null,
"achievement_count": 0,
"kudos_count": 0,
"comment_count": 0,
"athlete_count": 1,
"photo_count": 0,
"map": {
"id": "a6684924768",
"summary_polyline": "w{cdFeznfWLA?MIQE@AD@B{CtPBy@?n@^JDEHCCM@ICq@FQ?K@HLDj@e@JAf@TRD^Rp@RRJn@Vh@HBDVJ|@VHBGENDNPn@VD?b@VJVH\\FFHN",
"resource_state": 2
},
"trainer": false,
"commute": false,
"manual": false,
"private": false,
"visibility": "everyone",
"flagged": false,
"gear_id": null,
"start_latlng": [
37.544444063678384,
127.05715290270746
],
"end_latlng": [
37.5420739967376,
127.05358958803117
],
"start_latitude": 37.544444063678384,
"start_longitude": 127.05358958803117,
"average_speed": 4.87,
"max_speed": 23.412,
"has_heartrate": false,
"heartrate_opt_out": false,
"display_hide_heartrate_option": false,
"elev_high": 20.4,
"elev_low": 18.8,
"upload_id": 7109387963,
"upload_id_str": "7109387963",
"external_id": "D893BB27-E4B0-4C08-B403-A669762F5EA5-activity.fit",
"from_accepted_tag": false,
"pr_count": 0,
"total_photo_count": 0,
"has_kudoed": false
}
]
선수 활동 가져오기
인증된 운동선수가 소유한 주어진 활동을 반환합니다.
모든 사람 및 팔로어 활동에 대해 읽습니다.
나만의 활동에는 activity:read_all이 필요합니다.
request
curl -X GET "https://www.strava.com/api/v3/activities/6684924768" -H "accept: application/json" -H "authorization: Bearer fe170ffa1dz663v5fb33ec60187"
response
{
"resource_state": 3,
"athlete": {
"id": ,
"resource_state": 1
},
"name": "첫번째 달리기 테스트트2",
"distance": 754.8,
"moving_time": 155,
"elapsed_time": 161,
"total_elevation_gain": 0,
"type": "Run",
"workout_type": 3,
"id": ,
"start_date": "2022-02-15T05:16:12Z",
"start_date_local": "2022-02-15T14:16:12Z",
"timezone": "(GMT+09:00) Asia/Seoul",
"utc_offset": 32400,
"location_city": null,
"location_state": null,
"location_country": null,
"achievement_count": 0,
"kudos_count": 0,
"comment_count": 0,
"athlete_count": 1,
"photo_count": 0,
"map": {
"id": "a6684924768",
"polyline": "w{cdFeznfWLA?MIQE@AD@B{CtPBy@?n@^JDEHCCM@ICq@FQ?K@HLDj@e@JAf@TRD^Rp@RRJn@Vh@HBDVJ|@VHBGENDNPn@VD?b@VJVH\\FFHN",
"resource_state": 3,
"summary_polyline": "w{cdFeznfWLA?MIQE@AD@B{CtPBy@?n@^JDEHCCM@ICq@FQ?K@HLDj@e@JAf@TRD^Rp@RRJn@Vh@HBDVJ|@VHBGENDNPn@VD?b@VJVH\\FFHN"
},
"trainer": false,
"commute": false,
"manual": false,
"private": false,
"visibility": "everyone",
"flagged": false,
"gear_id": null,
"start_latlng": [
37.544444063678384,
127.05715290270746
],
"end_latlng": [
37.5420739967376,
127.05358958803117
],
"start_latitude": 37.544444063678384,
"start_longitude": 127.05358958803117,
"average_speed": 4.87,
"max_speed": 23.412,
"has_heartrate": false,
"heartrate_opt_out": false,
"display_hide_heartrate_option": false,
"elev_high": 20.4,
"elev_low": 18.8,
"upload_id": 7109387963,
"upload_id_str": "7109387963",
"external_id": "D893BB27-E4B0-4C08-B403-A669762F5EA5-activity.fit",
"from_accepted_tag": false,
"pr_count": 0,
"total_photo_count": 0,
"has_kudoed": false,
"description": null,
"calories": 0,
"perceived_exertion": 2,
"prefer_perceived_exertion": false,
"segment_efforts": [],
"splits_metric": [
{
"distance": 754.8,
"elapsed_time": 160,
"elevation_difference": -0.3,
"moving_time": 155,
"split": 1,
"average_speed": 4.87,
"average_grade_adjusted_speed": 4.86,
"pace_zone": 0
}
],
"splits_standard": [
{
"distance": 754.8,
"elapsed_time": 160,
"elevation_difference": -0.3,
"moving_time": 155,
"split": 1,
"average_speed": 4.87,
"average_grade_adjusted_speed": 4.86,
"pace_zone": 0
}
],
"laps": [
{
"id": 21961119754,
"resource_state": 2,
"name": "Lap 1",
"activity": {
"id": 6684924768,
"resource_state": 1
},
"athlete": {
"id": 98989256,
"resource_state": 1
},
"elapsed_time": 161,
"moving_time": 155,
"start_date": "2022-02-15T05:16:12Z",
"start_date_local": "2022-02-15T14:16:12Z",
"distance": 754.78,
"start_index": 0,
"end_index": 147,
"total_elevation_gain": 0,
"average_speed": 4.87,
"max_speed": 23.412,
"device_watts": false,
"lap_index": 1,
"split": 1,
"pace_zone": 0
}
],
"best_efforts": [
{
"id": 17036451731,
"resource_state": 2,
"name": "400m",
"activity": {
"id": 6684924768,
"resource_state": 1
},
"athlete": {
"id": 98989256,
"resource_state": 1
},
"elapsed_time": 46,
"moving_time": 32,
"start_date": "2022-02-15T05:16:31Z",
"start_date_local": "2022-02-15T14:16:31Z",
"distance": 400,
"start_index": 18,
"end_index": 52,
"pr_rank": null,
"achievements": []
}
],
"photos": {
"primary": null,
"count": 0
},
"stats_visibility": [
{
"type": "heart_rate",
"visibility": "everyone"
},
{
"type": "pace",
"visibility": "everyone"
},
{
"type": "power",
"visibility": "everyone"
},
{
"type": "speed",
"visibility": "everyone"
},
{
"type": "calories",
"visibility": "everyone"
}
],
"hide_from_home": false,
"device_name": "Strava iPhone App",
"embed_token": "708bec00b4671905843cdf4ab713e549cd06406e",
"private_note": null,
"similar_activities": {
"effort_count": 1,
"average_speed": 4.869548576108871,
"min_average_speed": 4.869548576108871,
"mid_average_speed": 4.869548576108871,
"max_average_speed": 4.869548576108871,
"pr_rank": null,
"frequency_milestone": null,
"trend": {
"speeds": [
4.869548576108871
],
"current_activity_index": 0,
"min_speed": 4.869548576108871,
"mid_speed": 4.869548576108871,
"max_speed": 4.869548576108871,
"direction": 0
},
"resource_state": 2
},
"available_zones": []
}