NAV Navbar
shell

Introduction

Welcome to the Wahoo Fitness OAuth2 API! You can use our API to access Wahoo Fitness OAuth2 API endpoints, which can get information on your user profile and workout history stored in our cloud.

We have language bindings in Shell! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Data Model

This diagram shows how the data records are related within the API

UserWorkout SummaryWorkout

Registration

Create a user account and register your app in our developer portal (https://developers.wahooligan.com). Your app can be set to 'Sandbox' or 'Production'. With 'Sandbox' apps you will be able to test and see your changes immediately but with very limited throughput. Production apps will have to go through a review process with Wahoo Fitness, and when approved your app can be released with a higher rate limit.

Rate Limiting

Rate limits and usage are included within each HTTP response header

  X-RateLimit-Limit: <limit_day>, <limit_hour>, <limit_5min>
  X-RateLimit-Remaining: <remaining_day>, <remaining_hour>, <remaining_5min>
  X-RateLimit-Reset: <seconds_until_reset>

Sample header values for a successful response:

  X-RateLimit-Limit: 5000, 1000, 200
  X-RateLimit-Remaining: 4999, 999, 199
  X-RateLimit-Reset: 0

Sample header values for a rate limited response:

  X-RateLimit-Limit: 5000, 1000, 200
  X-RateLimit-Remaining: 4800, 800, 0
  X-RateLimit-Reset: 300

The following chart shows how your app will be rate limited. If you require a higher throughput, please contact support to request an increase.

Interval Sandbox Apps Production Apps
Requests every 5 Min: 25 200
Requests per Hour: 100 1000
Requests per Day: 250 5000

Authentication

Workflow

OAuth2 Uses the following authentication workflow. The goal is to obtain an access_token for a user that can be used for accessing Wahoo's API on the user's behalf.

The Wahoo API does allow users to use the PKCE flow for authorization. If you would like to use the PKCE flow for your application please go to My Developer Apps -> select edit on your app and then select 'Yes' under the question asking if you would like to use PKCE for your application. If you would like to learn more about the PKCE flow please visit their documentation https://www.oauth.com/oauth2-servers/pkce/

Prior to starting the OAuth2 workflow please make sure the application has been created here(https://developers.wahooligan.com/applications) in order to obtain the client id and client secret.

Step 1. Send the user to Wahoo in order to login and grant access to your app using the following url:

https://<base_url>/oauth/authorize?client_id=<client_id>&redirect_uri=<redirect_uri>&scope=<scopes>&response_type=code

Step 2. After successful authorization the user will be redirected back to your redirect_uri with a code.

<redirect_uri>?code=<code>

Step 3. Send an HTTP POST to Wahoo with the code and your app's OAuth2 credentials and receive the access_token and refresh_token

https://<base_url>/oauth/token?client_secret=<client_secret>&code=<code>&redirect_uri=<redirect_uri>&grant_type=authorization_code&client_id=<client_id>

Step 4. When the access_token expires after 2 hours you can use the refresh_token to get a new access_token and a new refresh_token

https://<base_url>/oauth/token?client_secret=<client_secret>&client_id=<client_id>&grant_type=refresh_token&refresh_token=<refresh_token>

Step 5. You are now ready to send requests to our API by putting the new access_token within the following HTTP Header:

"Authorization": "Bearer <access_token>"

Attribute Notes
base_url: api.wahooligan.com
client_id: You can get your app's client_id from the developer portal.
client_secret: You can get your app's client_secret from the developer portal.
redirect_uri: You can set the redirect_uri for your app in the developer portal.
scopes: See Authorization Scopes
access_token: Returned in Step 3; Used for API calls to view/manage user data.
refresh_token: Returned in Step 3; Used to refresh the access_token.
expires_in: Returned in Step 3; Indicates when the access_token will expire.
code_challenge: Required for PKCE in Step 1; A SHA256 hash value for the code verifier, must be Base64 encoded
code_verifier: Required for PKCE in Step 3; The original code verifier for the PKCE request

Our API returns strings for decimal data types in our responses. This is because our API uses JSON for responses and requests. Please be sure to use headers for Content-Type as application/JSON:

Content-Type: application/json

Authorization

# With shell, you can append the requested scopes as a space separated list of values
curl "<base_url>/oauth/authorize?scope=user_read%20user_write"
  -H "Authorization: Bearer <Token>"

Applications must only request permission for resources they intend to access or modify. You can choose which permission scopes your app will request either by setting the scopes for your app in the developer portal or by sending a space separated list of scopes as a parameter in the oauth/authorize request.

We support the following OAuth 2.0 permission scopes:

Scope Description
email Access your email address
user_read Access your user data
user_write Update your user data
workouts_read Access your workout history
workouts_write Update your workout history
offline_data Receive data even when the app is closed

Please note: If the user_read scope is not included the API will return a 403 response.

Deauthorize

# With shell, you can revoke access to an application
curl -X "DELETE" "<base_url>/v1/permissions"
  -H "Authorization: Bearer <Token>"

Application access can be revoked by sending a request to delete all permissions.

HTTP Request

DELETE https://api.wahooligan.com/v1/permissions

Plans

Plan records hold information pertaining to the structure of a workout that can be played on Wahoo devices and applications. A plan record includes a file which holds details about the intervals and targets to be performed during a workout.

For Information regarding how to build your plan file see Plan Files.

Wahoo uses a library data model approach for planned workouts. A user should only have a single copy of a plan that can then be referenced by multiple workout instances. As a result creating a planned workout is a two-step process:

  1. Create a plan record to place the plan in the user's library and receive a plan id.
  2. Create (or update) a workout record with a reference to the plan id.

It is best practice to use the external_id and provider_updated_at fields to prevent duplicate records and ensure only a single copy of a plan is uploaded to a user's library.

Plan Files

The plan file contains a single JSON object with the following sections:

Detailed information regarding the structure of the plan file can be found in the link below.

Instructions for creating a plan file

Create a Plan

curl --header "Authorization: Bearer users-token-goes-here"  -X POST
  -d 'plan[file]=data:application/json;base64,<base64-encoded-plan-file>&
      plan[filename]=plan.json&
      plan[external_id]=P0001&
      plan[provider_updated_at]=2023-01-01T12:00:00.000Z'  https://api.wahooligan.com/v1/plans

Sample Response:

{
  "id": 5,
  "user_id": 4,
  "name": "Special Plan",
  "description": "Warmup for 10 minutes, FTP ladder up, cool down for 5 minutes",
  "file": {
      "url": "https://cdn.wahooligan.com/wahoo-cloud/production/uploads/plan/file/RGpT2JYKbmHzqRu2WFHHvg/plan.json"
  },
  "workout_type_family_id": 0,
  "workout_type_location_id": 255,
  "external_id": "P0001",
  "provider_updated_at": "2023-01-01T12:00:00.000Z",
  "deleted": false,
  "updated_at": "2023-12-19T22:26:36.000Z",
  "created_at": "2023-12-19T22:26:36.000Z"
}

Requires the plans_write scope

Creates a plan for the authenticated user.

HTTP Request

POST https://api.wahooligan.com/v1/plans

Parameters

Parameter Type Required Description
plan[file] File yes Base64 encoded JSON file
plan[filename] String no The name of the plan file
plan[external_id] String yes Unique external Id of the plan
plan[provider_updated_at] Date yes External date/time the file was updated externally

Get a Plan

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/plans/5

Sample Response:

{
  "id": 5,
  "user_id": 4,
  "name": "Special Plan",
  "description": "Warmup for 10 minutes, FTP ladder up, cool down for 5 minutes",
  "file": {
      "url": "https://cdn.wahooligan.com/wahoo-cloud/production/uploads/plan/file/RGpT2JYKbmHzqRu2WFHHvg/plan.json"
  },
  "workout_type_family_id": 0,
  "workout_type_location_id": 255,
  "external_id": "P0001",
  "provider_updated_at": "2023-01-01T12:00:00.000Z",
  "deleted": false,
  "updated_at": "2023-12-19T22:26:36.000Z",
  "created_at": "2023-12-19T22:26:36.000Z"
}

Requires the plans_read scope

Returns a plan from the library of the authenticated user.

HTTP Request

GET https://api.wahooligan.com/v1/plans/:id

Update a Plan

curl --header "Authorization: Bearer users-token-goes-here"  -X PUT
  -d 'plan[file]=data:application/json;base64,<base64-encoded-plan-file>&
      plan[filename]=plan.json&
      plan[provider_updated_at]=2023-01-04T12:00:00.000Z'  https://api.wahooligan.com/v1/plans/5

Sample Response:

{
  "id": 5,
  "user_id": 4,
  "name": "Special Plan",
  "description": "Warmup for 10 minutes, FTP ladder up, cool down for 5 minutes",
  "file": {
      "url": "https://cdn.wahooligan.com/wahoo-cloud/production/uploads/plan/file/RGpT2JYKbmHzqRu2WFHHvg/plan.json"
  },
  "workout_type_family_id": 0,
  "workout_type_location_id": 255,
  "external_id": "P0001",
  "provider_updated_at": "2023-01-04T12:00:00.000Z",
  "deleted": false,
  "updated_at": "2023-12-19T22:26:36.000Z",
  "created_at": "2024-01-05T05:18:21.000Z"
}

Requires the plans_write scope

Updates a plan that is in the library of the authenticated user.

HTTP Request

PUT https://api.wahooligan.com/v1/plans/:id

Query Parameters

Parameter Type Required Description
plan[file] File yes Base64 encoded JSON file
plan[filename] String no The name of the plan file
plan[provider_updated_at] Date yes External date/time the file was updated externally

Delete a Plan

curl -X DELETE --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/plans/5

Requires the plans_write scope

Deletes a plan that is in the library of the authenticated user.

HTTP Request

DELETE https://api.wahooligan.com/v1/plans/:id

Power Zones

Create a Power Zone

curl --header "Authorization: Bearer users-token-goes-here"  -X POST
  -d 'power_zone[zone_1]=100
      power_zone[zone_2]=120&
      power_zone[zone_3]=120&
      power_zone[zone_4]=120&
      power_zone[zone_5]=120&
      power_zone[zone_6]=120&
      power_zone[zone_7]=120&
      power_zone[ftp]=400&
      power_zone[zone_count]=8&
      power_zone[workout_type_id]=10&
      power_zone[workout_type_family_id]=6&
      power_zone[workout_type_location_id]=8&
      power_zone[critical_power]=324'  https://api.wahooligan.com/v1/power_zones

Sample Response:

{
  "id": 1,
  "user_id": 1,
  "zone_1": 100,
  "zone_2": 120,
  "zone_3": 140,
  "zone_4": 150,
  "zone_5": 200,
  "zone_6": 300,
  "zone_7": 400,
  "ftp": 400,
  "zone_count": 8,
  "workout_type_id": 10,
  "workout_type_family_id": 6,
  "workout_type_location_id": 8,
  "critical_power": 324,
  "originator_type": 0,
  "fitness_app_id": 6,
  "created_at": "2016-01-27T16:18:53.927Z",
  "updated_at": "2016-01-27T16:18:53.927Z"
}

Requires the power_zones_write scope

Creates a power zone for the authenticated user.

HTTP Request

POST https://api.wahooligan.com/v1/power_zones

Parameters

Parameter Type Required Default Description
power_zone[zone_1] Number no Power Zone Value
power_zone[zone_2] Number no Power Zone Value
power_zone[zone_3] Number no Power Zone Value
power_zone[zone_4] Number no Power Zone Value
power_zone[zone_5] Number no Power Zone Value
power_zone[zone_6] Number no Power Zone Value
power_zone[zone_7] Number no Power Zone Value
power_zone[zone_count] Number no Power Zone Total Count
power_zone[ftp] Number no Functional Threshold Power
power_zone[critical_power] Number no MMP/Best average power
power_zone[workout_type_id] Number no ID of the Workout Type
power_zone[workout_type_family_id] Number no ID of the Workout Type
power_zone[workout_type_location_id] Number no ID of the Workout Type

Get a Power Zone

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/power_zones/56519

Sample Response:

{
  "id": 56519,
  "user_id": 1,
  "zone_1": 100,
  "zone_2": 120,
  "zone_3": 140,
  "zone_4": 150,
  "zone_5": 200,
  "zone_6": 300,
  "zone_7": 400,
  "ftp": 400,
  "zone_count": 8,
  "workout_type_id": 10,
  "workout_type_family_id": 6,
  "workout_type_location_id": 8,
  "critical_power": 324,
  "originator_type": 0,
  "fitness_app_id": 6,
  "created_at": "2016-01-27T16:18:53.927Z",
  "updated_at": "2016-01-27T16:18:53.927Z"
}

Requires the power_zones_read scope

Returns a power zone for the current authenticated user.

HTTP Request

GET https://api.wahooligan.com/v1/power_zones/:id

Update a Power Zone

curl --header "Authorization: Bearer users-token-goes-here" -X PUT
  -d power_zone[ftp]=300 https://api.wahooligan.com/v1/power_zones/56519

Sample Response:

{
  "id": 56519,
  "user_id": 1,
  "zone_1": 100,
  "zone_2": 120,
  "zone_3": 140,
  "zone_4": 150,
  "zone_5": 200,
  "zone_6": 300,
  "zone_7": 400,
  "ftp": 300,
  "zone_count": 8,
  "workout_type_id": 10,
  "workout_type_family_id": 6,
  "workout_type_location_id": 8,
  "critical_power": 324,
  "originator_type": 0,
  "fitness_app_id": 6,
  "created_at": "2016-01-27T16:18:53.927Z",
  "updated_at": "2016-01-27T16:18:53.927Z"
}

Requires the power_zones_write scope

Updates a power zone for the authenticated user.

HTTP Request

POST https://api.wahooligan.com/v1/power_zones

Parameters

Parameter Type Required Default Description
power_zone[zone_1] Number no Power Zone Value
power_zone[zone_2] Number no Power Zone Value
power_zone[zone_3] Number no Power Zone Value
power_zone[zone_4] Number no Power Zone Value
power_zone[zone_5] Number no Power Zone Value
power_zone[zone_6] Number no Power Zone Value
power_zone[zone_7] Number no Power Zone Value
power_zone[zone_count] Number no Power Zone Total Count
power_zone[ftp] Number no Functional Threshold Power
power_zone[critical_power] Number no Critical Power
power_zone[workout_type_id] Number no ID of the Workout Type
power_zone[workout_type_location_id] Number no ID of the Workout Type Location
power_zone[workout_type_family_id] Number no ID of the Workout Type Family

Get Power Zones

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/power_zones

Sample Response:

{
  "power_zones": 
  [
    {
      "id": 1,
      "user_id": 1,
      "zone_1": 100,
      "zone_2": 120,
      "zone_3": 140,
      "zone_4": 150,
      "zone_5": 200,
      "zone_6": 300,
      "zone_7": 400,
      "ftp": 400,
      "zone_count": 8,
      "workout_type_id": 10,
      "workout_type_family_id": 6,
      "workout_type_location_id": 8,
      "critical_power": 324,
      "originator_type": 0,
      "fitness_app_id": 6,
      "created_at": "2016-01-27T16:18:53.927Z",
      "updated_at": "2016-01-27T16:18:53.927Z"
    }
  ]
}

Requires the power_zones_read scope

Returns the power zones for the authenticated user.

HTTP Request

GET https://api.wahooligan.com/v1/power_zones

Delete a Power Zone

curl -X DELETE --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/power_zones/:id

Requires the power_zones_write scope

Deletes a power zone that is owned by the authenticated user.

HTTP Request

DELETE https://api.wahooligan.com/v1/power_zones/:id

Users

Applications can get and update the attributes of the authenticated user.

Get Authenticated User

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/user

Sample Response:

{
  "id": 60462,
  "height": "2.0",
  "weight": "80.0",
  "first": "Bob",
  "last": "Smith",
  "email": "sample@test-domain.com",
  "birth": "1980-10-02",
  "gender": 1,
  "created_at": "2018-10-23T15:38:23.000Z",
  "updated_at": "2018-10-24T20:46:40.000Z"
}

Requires user_read scope

Returns the authenticated user along with email if email scope is included.

HTTP Request

GET https://api.wahooligan.com/v1/user

Update User

curl --header "Authorization: Bearer users-token-goes-here"
     -X PUT -d user[gender]=1 https://api.wahooligan.com/v1/user

Sample Response:

{
  "id": 60462,
  "height": "2.0",
  "weight": "80.0",
  "first": "Bob",
  "last": "Smith",
  "email": "bob.s@wahoofitness.com",
  "birth": "1980-10-02",
  "gender": 1,
  "created_at": "2018-10-23T15:38:23.000Z",
  "updated_at": "2018-10-24T20:46:40.000Z"
}

Requires the user_write scope

Updates the current authenticated user.

HTTP Request

PUT https://api.wahooligan.com/v1/user

Parameters

Parameter Type Required Description
user[email] String no Well formed email address, must be unique in the system
user[first] String no First name
user[last] String no Last name
user[height] Decimal no Height in meters
user[weight] Decimal no Weight in kilograms
user[birth ] Date no Date of birth formatted as YYYY-MM-DD
user[gender] 0,1,2,3 no Use 0 for male, 1 for female, 2 for other, and 3 for prefer not to say

Workouts

A workout record holds information about a single workout event. A workout becomes a structured workout when it includes an association to a plan.

What is a daycode?

Daycodes can be used to specify a specific date a user would like a workout on without having to also tie the workout to a start time. A daycode is an integer that is calculated based on how many days it has been since January 1st 2020 (daycode of 1), for example 1/1/2021 would have a daycode of 366 becuase 2020 was a leap year, and 09/12/2024 would have a daycode of 1716.

Create a Workout

curl --header "Authorization: Bearer users-token-goes-here"  -X POST
  -d 'workout[name]="Friday fun"&
      workout[workout_token]=123&
      workout[workout_type_id]=40&
      workout[starts]=2015-08-12T09:00:00.000Z&
      workout[minutes]=12'  https://api.wahooligan.com/v1/workouts

Sample Response:

{
    "id": 56519,
    "starts": "2015-08-12T09:00:00.000Z",
    "minutes": 12,
    "name": "Friday Fun",
    "created_at": "2018-10-23T20:41:55.000Z",
    "updated_at": "2018-10-23T20:41:55.000Z",
    "plan_id": null,
    "workout_token": "123",
    "workout_type_id": 40
}

Requires the workouts_write scope

Creates a workout for the authenticated user.

If you would like to create a planned structured workout please make sure to create a plan file that can be attached to the workout. Documentation for creating a plan file can be found under the Plans tab.

HTTP Request

POST https://api.wahooligan.com/v1/workouts

Parameters

Parameter Type Required Default Description
workout[name] String yes The name of the workout
workout[workout_type_id] Number yes The type of the workout - Workout Types
workout[starts] Time yes Start time
workout[minutes] Number yes Duration of the workout in minutes
workout[workout_token] String no Can be used by the application to identify the workout
workout[plan_id] Number no null Id of the plan used in this workout
workout[day_code] Number no null The number of days since 1/1/2020
workout[workout_summary] Object no Include summary results - Workout Summary

Get a Workout

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/workouts/56519

Sample Response:

{
  "id": 56519,
  "starts": "2015-08-12T09:00:00.000Z",
  "minutes": 12,
  "name": "Friday Fun",
  "plan_id": null,
  "workout_token": "123",
  "workout_type_id": 40,
  "workout_summary": null,
  "created_at": "2018-10-23T20:41:55.000Z",
  "updated_at": "2018-10-23T20:41:55.000Z"
}

Requires the workouts_read scope

Returns a workout for the current authenticated user.

HTTP Request

GET https://api.wahooligan.com/v1/workouts/:id

Update a Workout

curl --header "Authorization: Bearer users-token-goes-here" -X PUT
  -d workout[name]="Friday afternoon" https://api.wahooligan.com/v1/workouts/56519

Sample Response:

{
  "id": 56519,
  "starts": "2015-08-12T09:00:00.000Z",
  "minutes": 12,
  "name": "Friday afternoon",
  "plan_id": null,
  "workout_token": "123",
  "workout_type_id": 40,
  "workout_summary": null,
  "created_at": "2018-10-23T20:41:55.000Z",
  "updated_at": "2018-10-23T20:41:55.000Z"
}

Requires the workouts_write scope

Updates a workout for the authenticated user.

HTTP Request

PUT https://api.wahooligan.com/v1/workouts/:id

Query Parameters

Parameter Type Required Description
workout[name] String no The name of the workout
workout[workout_token] String no Can be used by the application to identify the workout
workout[starts] Time no Start time
workout[minutes] Number no Duration of the workout in minutes
workout[plan_id] Number no Id of the plan used in this workout
workout[workout_type_id] Number no The type of the workout - Workout Types
workout[day_code ] Number no The number of days since 1/1/2020
workout[workout_summary] Object no Include summary results - Workout Summary

Get all Workouts

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/workouts

Sample Response:

{
  "workouts": [
    {
      "id": 56519,
      "starts": "2015-08-12T09:00:00.000Z",
      "minutes": 12,
      "name": "Friday afternoon",
      "plan_id": null,
      "workout_token": "123",
      "workout_type_id": 40,
      "workout_summary": null,
      "created_at": "2018-10-23T20:41:55.000Z",
      "updated_at": "2018-10-23T20:41:55.000Z"
    }
  ],
  "total": 1,
  "page": 1,
  "per_page": 30,
  "order": "descending",
  "sort": "starts"
}

Requires the workouts_read scope

Returns all workouts for the authenticated user. The workout are always sorted by the starts field in descending order. By default the most recent 30 workouts are returned. The per_page parameter can be used to adjust the number of workouts returned.

In the response the total attribute is the total number of workouts for the current user.

HTTP Request

GET https://api.wahooligan.com/v1/workouts

Query Parameters

Parameter Type Required Default Description
page integer no 1 Used for pagination.
per_page integer no 30 Limits the number of workouts returned.

Delete a Workout

curl -X DELETE --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/workouts/:id

Requires the workouts_write scope

Deletes a workout that is owned by the authenticated user.

HTTP Request

DELETE https://api.wahooligan.com/v1/workouts/:id

Workout File Uploads

Create a Workout File Upload

curl --header "Authorization: Bearer users-token-goes-here"  -X POST
  -d 'workout_file_upload[file]="data:application/vnd.fit;base64,RmFrZSBmaXQgZmlsZQ=="&
      workout_file_upload[filename]="workout_results.fit"&
      workout_file_upload[time_zone]="America/New_York"' https://api.wahooligan.com/v1/workout_file_uploads

Sample Response:

{
    "id": 56519,
    "starts": "2015-08-12T09:00:00.000Z",
    "minutes": 12,
    "name": "Friday Fun",
    "created_at": "2018-10-23T20:41:55.000Z",
    "updated_at": "2018-10-23T20:41:55.000Z",
    "plan_id": null,
    "workout_type_id": 40
}

Requires the workouts_write scope

Send the results of a workout to Wahoo for processing. This endpoint will attempt to process the uploaded FIT file and generate the correct workout and workout summary objects. If a workout object has already been created it is recommended to specify the target_workout_id within the request to ensure that the workout summary is associated with the correct workout.

This endpoint will return a workout_file_upload object that will contain the current status of the upload.

HTTP Request

POST https://api.wahooligan.com/v1/workout_file_uploads

Parameters

Parameter Type Required Default Description
workout_file_upload[file] File yes Base64 encoded FIT File
workout_file_upload[filename] String no The name of the workout file
workout_file_upload[time_zone] String no The time zone where the FIT file was recorded
workout_file_upload[workout_name] String no Name to use for the workout summary
workout_file_upload[target_workout_id] Number no Wahoo Id of the workout this file should be associated with

Get a Workout File Upload

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/workout_file_uploads/:token

Sample Response:

{
    "id": 5,
    "user_id": 1,
    "token": "fRa2HvZ1N0WxuHw",
    "status": "pending",
    "time_zone": null,
    "workout_id": null,
    "workout_summary_id": null,
    "workout_file_id": null,
    "workout_name": null,
    "error": null,
    "target_workout_id": null,
    "created_at": "2018-10-23T20:43:50.000Z",
    "updated_at": "2018-10-23T20:43:50.000Z"
}

Requires the workouts_write scope

Returns the workout file upload object with the corresponding token. Since the processing of a Workout File Upload is asynchronous it may take a few seconds to a few hours before the upload has been processed. On average Workout File Uploads are processed in less than 5 seconds.

When the status is complete the file has completed processing and the workout_id and workout_summary_id fields will be populated with values that can be used to fetch those objects from the workouts and workout_summary endpoints.

When the status is error the error attribute will contain additional information regarding the failure of the upload.

HTTP Request

GET https://api.wahooligan.com/v1/workout_file_uploads/:token

Upload Status

Status Description
pending The file is waiting to be processed
in_progress The file is currently being processed and should complete within 1-5 seconds
complete The file has successfully been processed
error There was an error processing the file
duplicate The uploaded file exactly matches a previously uploaded file

Workout Summaries

Workout Summary records contain the results of a workout.

How to download a file

The Workout Summary show endpoint will provide the url for the workout fit file. If you would like to download the fit file please copy the url, then paste it into your browser or make a GET call to download the fit ile.

Create a Workout Summary

curl --header "Authorization: Bearer users-token-goes-here" -X POST
  -d workout_summary[power_avg]="240.52" https://api.wahooligan.com/v1/workouts/56519/workout_summary

Sample Response:

{
    "id": 8297,
    "ascent_accum": "450.00",
    "cadence_avg": "50.00",
    "calories_accum": "1500.00",
    "distance_accum": "24909.71",
    "duration_active_accum": "179.00",
    "duration_paused_accum": "95.00",
    "duration_total_accum": "275.24",
    "heart_rate_avg": "124.54",
    "power_bike_np_last": "150.00",
    "power_bike_tss_last": "304.90",
    "power_avg": "94.59",
    "speed_avg": "10.75",
    "work_accum": "1041480.00",
    "created_at": "2018-10-23T20:43:50.000Z",
    "updated_at": "2018-10-23T20:43:50.000Z",
    "file": {
        "url": "https://server.com/4_Mile_Segment_.fit"
    }
}

Requires the workouts_write scope

Creates a workout summary and associates it with a workout. If a workout summary already exists for the workout then the workout summary is updated.

HTTP Request

POST https://api.wahooligan.com/v1/workouts/:id/workout_summary

Parameters

Parameter Type Description
workout_summary[ascent_accum] decimal Ascent in meters
workout_summary[cadence_avg] decimal Average rotations per minute
workout_summary[calories_accum] decimal Calories (kCal)
workout_summary[distance_accum] decimal Meters
workout_summary[duration_active_accum] decimal Seconds
workout_summary[duration_paused_accum] decimal Seconds
workout_summary[duration_total_accum] decimal Seconds
workout_summary[heart_rate_avg] decimal bpm
workout_summary[power_avg] decimal Watts
workout_summary[power_bike_np_last] decimal Watts
workout_summary[power_bike_tss_last] decimal unitless
workout_summary[speed_avg] decimal Meters/Sec
workout_summary[work_accum] decimal joules
workout_summary[file] File Fit file

Get a Workout Summary

Sample Response:

{
    "id": 8297,
    "ascent_accum": "450.00",
    "cadence_avg": "50.00",
    "calories_accum": "1500.00",
    "distance_accum": "24909.71",
    "duration_active_accum": "179.00",
    "duration_paused_accum": "95.25",
    "duration_total_accum": "275.00",
    "heart_rate_avg": "100.00",
    "power_bike_np_last": "150.00",
    "power_bike_tss_last": "304.90",
    "power_avg": "94.59",
    "speed_avg": "10.75",
    "work_accum": "1041480.00",
    "time_zone": "America/Denver",
    "file": {
        "url": "https://server.com/4_Mile_Segment_.fit"
    },
    "created_at": "2018-10-23T20:43:50.000Z",
    "updated_at": "2018-10-23T20:43:50.000Z"
}

Requires the workouts_read scope

Returns the workout summary object for a workout. When a workout is created, the workout summary will be empty until it is updated.

curl --header "Authorization: Bearer users-token-goes-here" https://api.wahooligan.com/v1/workouts/:id/workout_summary

HTTP Request

GET https://api.wahooligan.com/v1/workouts/:id/workout_summary

Webhooks

Receive API calls from Wahoo to your webhook url.

Please make sure the offline_data scope is added to receive webhooks.

If we do not receive an HTTP 200 response code we will retry the api call on the following retry schedule:

  1. After 30 minutes
  2. After 4 hours
  3. After 24 hours
  4. After 72 hours

API Calls will be sent via HTTP POST with the HTTP header Content-Type: application/json

It is possible for duplicate webhooks to be made when files are updated or deleted.

Settings

Setting Notes
webhook_enabled: Toggle the webhook api calls on/off.
webhook_url: Receive an HTTP POST with a JSON payload to this url.
webhook_token: Specify a token that you would like us to send. Any request that doesn't include this token should be ignored.

Workout Summary

Requires the offline_data scope

Sample Workout Summary Webhook Message

{
  "event_type": "workout_summary",
  "webhook_token": <webhook_token>,
  "user": {
    "id": 60462
  },
  "workout_summary": {
    "id": 8297,
    "ascent_accum": "450.00",
    "cadence_avg": "52.00",
    "calories_accum": "1500.00",
    "distance_accum": "24909.71",
    "duration_active_accum": "179.00",
    "duration_paused_accum": "85.00",
    "duration_total_accum": "275.20",
    "heart_rate_avg": "124.23",
    "power_bike_np_last": "150.01",
    "power_bike_tss_last": "304.90",
    "power_avg": "94.59",
    "speed_avg": "10.75",
    "work_accum": "104148000.01",
    "created_at": "2018-10-23T20:43:50.000Z",
    "updated_at": "2018-10-23T20:43:50.000Z",
    "file": {
      "url": "https://server.com/4_Mile_Segment_.fit"
    },
    "workout": {
      "id": 56519,
      "starts": "2015-08-12T09:00:00.000Z",
      "minutes": 12,
      "name": "Friday Fun",
      "created_at": "2018-10-23T20:41:55.000Z",
      "updated_at": "2018-10-23T20:41:55.000Z",
      "plan_id": null,
      "workout_token": "123",
      "workout_type_id": 40
    }
  }     
}

Workout Types

The Wahoo Fitness API supports the following workout locations, families and types:

Workout Types:

Id Description Location Family
0 BIKING OUTDOOR BIKING
1 RUNNING OUTDOOR RUNNING
2 FE INDOOR N/A
3 RUNNING_TRACK OUTDOOR TRACK
4 RUNNING_TRAIL OUTDOOR TRAIL
5 RUNNING_TREADMILL INDOOR RUNNING
6 WALKING OUTDOOR WALKING
7 WALKING_SPEED OUTDOOR WALKING
8 WALKING_NORDIC OUTDOOR WALKING
9 HIKING OUTDOOR WALKING
10 MOUNTAINEERING OUTDOOR WALKING
11 BIKING_CYCLECROSS OUTDOOR BIKING
12 BIKING_INDOOR INDOOR BIKING
13 BIKING_MOUNTAIN OUTDOOR BIKING
14 BIKING_RECUMBENT OUTDOOR BIKING
15 BIKING_ROAD OUTDOOR BIKING
16 BIKING_TRACK OUTDOOR BIKING
17 BIKING_MOTOCYCLING OUTDOOR BIKING
18 FE_GENERAL INDOOR N/A
19 FE_TREADMILL INDOOR N/A
20 FE_ELLIPTICAL INDOOR GYM
21 FE_BIKE INDOOR N/A
22 FE_ROWER INDOOR GYM
23 FE_CLIMBER INDOOR N/A
25 SWIMMING_LAP INDOOR SWIMMING
26 SWIMMING_OPEN_WATER OUTDOOR SWIMMING
27 SNOWBOARDING OUTDOOR SNOW_SPORT
28 SKIING OUTDOOR SNOW_SPORT
29 SKIING_DOWNHILL OUTDOOR SNOW_SPORT
30 SKIINGCROSS_COUNTRY OUTDOOR SNOW_SPORT
31 SKATING OUTDOOR SKATING
32 SKATING_ICE INDOOR SKATING
33 SKATING_INLINE INDOOR SKATING
34 LONG_BOARDING OUTDOOR SKATING
35 SAILING OUTDOOR WATER_SPORTS
36 WINDSURFING OUTDOOR WATER_SPORTS
37 CANOEING OUTDOOR WATER_SPORTS
38 KAYAKING OUTDOOR WATER_SPORTS
39 ROWING OUTDOOR WATER_SPORTS
40 KITEBOARDING OUTDOOR WATER_SPORTS
41 STAND_UP_PADDLE_BOARD OUTDOOR WATER_SPORTS
42 WORKOUT INDOOR GYM
43 CARDIO_CLASS INDOOR GYM
44 STAIR_CLIMBER INDOOR GYM
45 WHEELCHAIR OUTDOOR OTHER
46 GOLFING OUTDOOR OTHER
47 OTHER OUTDOOR OTHER
49 BIKING_INDOOR_CYCLING_CLASS INDOOR BIKING
56 WALKING_TREADMILL INDOOR WALKING
61 BIKING_INDOOR_TRAINER INDOOR BIKING
62 MULTISPORT OUTDOOR N/A
63 TRANSITION OUTDOOR N/A
64 EBIKING OUTDOOR BIKING
65 TICKR_OFFLINE OUTDOOR N/A
66 YOGA INDOOR GYM
67 RUNNING_RACE OUTDOOR RUNNING
68 BIKING_INDOOR_VIRTUAL INDOOR BIKING
69 MENTAL_STRENGTH INDOOR OTHER
70 HANDCYCLING OUTDOOR BIKING
71 RUNNING_INDOOR_VIRTUAL INDOOR RUNNING
255 UNKNOWN

Workout Type Locations:

Id Description
0 INDOOR
1 OUTDOOR
255 UNKNOWN

Workout Type Families:

Id Description
0 BIKING
1 RUNNING
2 SWIMMING
3 WATER SPORTS
4 SNOW SPORTS
5 SKATING
6 GYM
9 WALKING
30 N/A
31 OTHER
255 UNKNOWN

Errors

The Wahoo Fitness API uses the following error codes:

Code Description
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- You do not have access to the specified resource.
404 Not Found -- The specified resource could not be found.
405 Method Not Allowed -- You tried to access a resource with an invalid method.
406 Not Acceptable -- You requested a format that isn't json.
410 Gone -- The resource requested has been removed from our servers.
422 Unprocessable Entity -- One or more parameters supplied are missing or invalid or your app is not approved.
429 Too Many Requests -- You are sending too many requests in short period of time.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.