The Best Bike Split API

The Best Bike Split Partner API allows developers to connect to authorized user accounts to access course and race plan information. API data requests are limited to Premium Best Bike Split members. Changes may be made to add additional features or improve performance.

If you are interested in becoming an authorized BBS API Partner please contact us with your Company Name, Technical Contact and Project Description.


Version

1.0


Introduction

The Best Bike Split API is organized around REST. Our API is designed to use HTTP response codes to indicate API errors. JSON will be returned in all responses from the API, including errors.


Authorization

Best Bike Split uses the OAuth2 authentication protocol. This allows your applications to request authorization to a user's data. Each registered application will be assigned a client_id and client_secret. The SECRET should never be shared.

Sample Request

To request access to user data on behalf of your application, point the user to the Best Bike Split authorization page along with the required URL Parameters. The page will prompt the user to authorize the application. Please note that only users with a Premium or Coach Subscription may access the API.

Suggested Connect Button

connect with best bike split button (download | download at 2x)

This button should link to https://bestbikesplit.com/member-connect along with the assigned client_id and redirect_uri as shown below.

GET Resource URL

https://www.bestbikesplit.com/member-connect?

URL Parameters

client_id=ExampleApp&
redirect_uri=http://www.myExampleApp.com/app

Sample Response

Best Bike Split will respond to the user authorization selection by redirecting the user to the redirect_uri provided by your application. On success, a temporary code will be included with the redirect. If access is denied by the user a status=access_denied will be included in the redirect.

http://www.myExampleApp.com/app?code=xxxxxxxxxxxxxxxxxx

Authorization Parameters

Parameter Description Required
client_id
string
A unique client Id assigned by Best Bike Split to your company's APP. If you or your company is interested in working with our API, please contact us for details. Yes
redirect_uri
string
Specifies the URI to which the user's code should be returned to. Yes

Token Exchange

Upon successful authorization your application must now request a user access token through the following post call. This access token will be used for all future API calls and passed as authorization in the header parameters.

Sample Request

You can request a user token by sending the previously supplied temporary code as code and your application's SECRET code as client_secret in the post parameters.

POST Resource URL

https://www.bestbikesplit.com/api/v1/oauth

POST Parameters

code=xxxxxxxxxxxxxxxxxx
client_secret=xxxxxxxxxxxxxxxxxx

Sample Response

A unique access token will be returned as JSON for the user based on the code and client_secret passed in the post parameters.

{
   "access_token": "xxxxxxxxxxxxxxxxxx"		// unique token assigned per user
}

Token Exchange Parameters

Parameter Description Required
code
string
A temporary code assigned to the user. Yes
client_secret
string
A unique code assigned by Best Bike Split to your company's APP. Yes

Deauthorization

You can revoke access between the Best Bike Split user and your application by use of the deauthorize api call.

Sample Request

To revoke access between the Best Bike Split user and your application send the users's access_token in the header parameters.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

POST Resource URL

https://www.bestbikesplit.com/api/v1/deauthorize

Sample Response

A confirmation message will be returned as JSON for the user with the specific token passed as authorization in the header parameters.

{
   "reason": "The application has been deauthorized."	// confirmation of deauthorized user
}

Deauthorization Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes

Course Information

The following demonstrates how to retrieve a specific course's information and groups of courses based on search parameters.

Sample Request (specific)

You can pull information on a single course by sending the course's unique ID as course_id in the request parameters. In this example the course ID of 321 is passed in as a request parameter.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/course?

URL Parameters

course_id=321

Sample Response (specific)

Course information returned as JSON for the course with the specific id passed as course_id in the request parameters.

{
  courses:[
    {
      "course_id": 321,				// course unique identifier
      "course_name": "Ironman Coeur d'Alene",	// course name
      "course_city": "Coeur d'Alene",		// course city (start)
      "course_state": "ID",			// course state
      "course_country": "US",			// course country
      "start_latitude": 47.67597,		// course latitude (start)
      "start_longitude": -116.78881072,		// course longitude (start)
      "course_distance": 179408,		// course distance (meters)
      "course_verified": 1			// course verified (0 = false, 1 = true)
    }
  ]
}

Sample Request (group)

You can pull information for a group of courses by sending one or more request parameters without a specific course ID parameter. In this example the request parameter for the course's distance as course_distance is passed in. (note: to pull all courses, simply send the request with no search parameters)

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/course?

URL Parameters

course_distance=180000
&course_country=US

Sample Response (group)

Course information returned as JSON for the courses that matched the supplied course_distance request parameters.

{
  courses:[
    {
      "course_id": 321,				// course unique identifier
      "course_name": "Ironman Coeur d'Alene",	// course name
      "course_city": "Coeur d'Alene",		// course city (start)
      "course_state": "ID",			// course state
      "course_country": "US",			// course country
      "start_latitude": 47.67597,		// course latitude (start)
      "start_longitude": -116.78881072,		// course longitude (start)
      "course_distance": 179408,		// course distance (meters)
      "course_verified": 1			// course verified (0 = false, 1 = true)
    },
    {
      "course_id": 496,
      "course_name": "2014 Ironman World Championship",
      "course_city": "Kailua-Kona",
      "course_state": "HI",
      "course_country": "US",
      "start_latitude": 19.64021,
      "start_longitude": -155.99682617,
      "course_distance": 180887,
      "course_verified": 1
    }
  ]
}

Course Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes
course_id
integer
Specifies the exact course to pull. Course Id overrides all other search parameters. If no course Id is supplied then search parameters are used to pull courses based on those parameters. No
course_group
integer
Filter courses by the following groups. (range: 1 to 3, default: 1)
1 = your courses
2 = your public courses
3 = your private courses
No
course_name
string
Filter courses by name. (example: "Boston Marathon") No
course_city
string
Filter courses by city. (example: "Hopkinton") No
course_state
string
Filter courses by state. (example: "MA") All US states are standard 2 character abbreviations. No
course_country
string
Filter courses by country. (example: "US") No
course_distance
integer
Filter courses by distance in meters (example: "180000"). If a distance is supplied, all courses within +/- 10,000 meters of that distance will be pulled. No

Course Details

The following demonstrates how to retrieve a specific course's detailed information.

Sample Request (RAW)

You can pull information on a single course by sending the course's unique ID as course_id in the request parameters. In this example the course ID of 496 is passed in as a request parameter.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/course-details?

URL Parameters

course_id=496

Sample Response (RAW)

Course's detailed information returned as JSON for the course with the specific id passed as course_id and the dataType set to default (RAW) in the request parameters.

{
  course_details:[
    {
      "course_id": 496,				// course unique identifier
      "course_name": "IM World Championship",	// course name
      "data_type": "RAW",			// course data type
      "track_points":[				// course track points
          {
            "distance": 0,			// track distance (meters)
            "elevation": 1.1,			// track elevation (meters)
            "latitude": 19.64027,		// track latitude
            "longitude": -155.99675		// track longitude
          },
          {
            "distance": 10.712,
            "elevation": 1.4,
            "latitude": 19.64027,
            "longitude": -155.99675
          }
      ]
    }
  ]
}

Sample Request (GPX)

You can pull information on a single course as a base64 encoded GPX by sending the course's unique ID as course_id and setting the dataType in the request parameters. In this example the course ID of 496 and dataType of 2 is passed in as request parameters.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/course-details?

URL Parameters

course_id=496
&data_type=2

Sample Response (GPX)

Course's detailed information returned as JSON for the course with the specific id passed as course_id and the dataType set to 2 (base64 encoded GPX) in the request parameters.

{
  course_details:[
    {
      "course_id": 496,				// course unique identifier
      "course_name": "IM World Championship",	// course name
      "data_type": "GPX",			// course data type
      "course_file": "PD94bWwgdmVyc2l..."	// base64 encoded course GPX
    }
  ]
}

Course Details Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes
course_id
integer
Specifies the exact course to pull. Yes
data_type
integer
Set the data type to be returned. (range: 1 to 2, default: 1)
1 = raw json
2 = base64 encoded GPX
No

Race Plan Information

The following demonstrates how to retrieve a specific race's information and groups of races based on search parameters.

Sample Request (specific)

You can pull information on a single race by sending the race's unique ID as race_id in the request parameters. In this example the race ID of 123 is passed in as a request parameter.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/race?

URL Parameters

race_id=123

Sample Response (specific)

Race information returned as JSON for the race with the specific id passed as race_id in the request parameters.

{
  races:[
    {
      "race_id": 123,				// race unique identifier
      "race_name": "Ironman Texas",		// race name
      "course_id": 221,				// course unique identifier
      "course_name": "2016 IM Texas",		// course name
      "bike_name": "Trek",			// bike name
      "race_city": "Town Center",		// race city (start)
      "race_state": "TX",			// race state
      "race_country": "US",			// race country
      "race_distance": 179157.7,		// race distance (meters)
      "race_time": 20363.721,			// race time (seconds)
      "race_avg_speed": 8.7979,			// race average speed (meters/second)
      "race_avg_power": 178.89,			// race average power (watts)
      "race_avg_yaw": 6.4,			// race average yaw angle (degrees)
      "race_np": 182.01,			// race Normalized Power
      "race_if": 0.55,				// race Intensity Factor
      "race_tss": 172,				// race Training Stress Score
      "race_updated": "2016-04-20T14:23:08Z", 	// date and time of last record update
    }
  ]
}

Sample Request (group)

You can pull information for a group of races by sending one or more request parameters without a specific race ID parameter. In this example the request parameter for the races's distance as race_distance and country as race_country are passed in. (note: to pull all races, simply send the request with no search parameters)

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/race?

URL Parameters

race_distance=180000
&race_country=US

Sample Response (group)

Race information returned as JSON for the races that matched the supplied race_distance request parameters.

{
  races:[
    {
      "race_id": 123,				// race unique identifier
      "race_name": "Ironman Texas",		// race name
      "course_id": 221,				// course unique identifier
      "course_name": "2016 IM Texas",		// course name
      "bike_name": "Trek",			// bike name
      "race_city": "Town Center",		// race city (start)
      "race_state": "TX",			// race state
      "race_country": "US",			// race country
      "race_distance": 179157.7,		// race distance (meters)
      "race_time": 20363.721,			// race time (seconds)
      "race_avg_speed": 8.7979,			// race average speed (meters/second)
      "race_avg_power": 178.89,			// race average power (watts)
      "race_avg_yaw": 6.4,			// race average yaw angle (degrees)
      "race_np": 182.01,			// race Normalized Power
      "race_if": 0.55,				// race Intensity Factor
      "race_tss": 172,				// race Training Stress Score
      "race_updated": "2016-04-20T14:23:08Z", 	// date and time of last record update
    },
    {
      "race_id": 164,
      "race_name": "Kona 2016",
      "course_id": 496,
      "course_name": "IM World Championship",
      "bike_name": "Tri Bike",
      "race_city": "Kailua-Kona",
      "race_state": "HI",
      "race_country": "US",
      "race_distance": 180887.26,
      "race_time": 19270.626,
      "race_avg_speed": 9.3867,
      "race_avg_power": 239.85,
      "race_avg_yaw": 5.91,
      "race_np": 245.78,
      "race_if": 0.75,
      "race_tss": 300,
      "race_updated": "2016-04-11T12:10:05Z",
    }
  ]
}

Race Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes
race_id
integer
Specifies the exact race to pull. Race Id overrides all other search parameters. If no race Id is supplied then search parameters are used to pull races based on those parameters. No
race_name
string
Filter races by name. (example: "Ironman Texas") No
course_name
string
Filter races by course by name. (example: "IM Texas 2016") No
bike_name
string
Filter races by bike by name. (example: "Trek Speed Concept") No
race_city
string
Filter races by city. (example: "Town Center") No
race_state
string
Filter races by state. (example: "TX") All US states are standard 2 character abbreviations. No
race_country
string
Filter races by country. (example: "US") No
race_distance
integer
Filter races by distance in meters (example: "180000"). If a distance is supplied, all courses within +/- 10,000 meters of that distance will be pulled. No
list_type
integer
Set the list type to be returned. (range: 1 to 2, default: 1)
1 = all data
2 = race_id and race_name only
No
list_limit
integer
Limit the number of races returned (example: "10"). No

Race Plan Details

The following demonstrates how to retrieve a specific race's detailed information.

Sample Request (specific)

You can pull information on a single race by sending the race's unique ID as race_id in the request parameters. In this example the race ID of 164 is passed in as a request parameter.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

GET Resource URL

https://www.bestbikesplit.com/api/v1/race-details?

URL Parameters

race_id=164

Sample Response

Race's detailed information returned as JSON for the race with the specific id passed as race_id in the request parameters.

{
  race_details:[
    {
      "race_summary":[					// race summary
          {
            "race_id": 164,				// race unique identifier
            "race_name": "Kona 2016",			// race name
            "course_id": 496,				// course unique identifier
            "course_name": "IM World Championship",	// course name
            "bike_name": "Tri Bike",			// bike name
            "race_city": "Kailua-Kona",			// race city (start)
            "race_state": "HI",				// race state
            "race_country": "US",			// race country
            "race_distance": 180887.26,			// race distance (meters)
            "race_time": 19270.626,			// race time (seconds)
            "race_avg_speed": 9.3867,			// race average speed (meters/second)
            "race_avg_power": 239.85,			// race average power (watts)
            "race_avg_yaw": 5.91,			// race average yaw angle (degrees)
            "race_np": 245.78,				// race Normalized Power
            "race_if": 0.75,				// race Intensity Factor
            "race_tss": 300,				// race Training Stress Score
            "race_updated": "2016-04-11T12:10:05Z", 	// date and time of last record update
          }
      ],
      "course_points":[					// course points
          {
            "distance": 0,				// course distance (meters)
            "latitude": 19.64021,			// course latitude
            "longitude": -155.99683,			// course longitude
            "power": 250,				// course power (watts)
            "speed": 10.284				// course speed (meters/second)
          },
          {
            "distance": 1885.315,
            "latitude": 19.64867,
            "longitude": -156.00451,
            "power": 247,
            "speed": 9.902
          }
      ],
      "track_points":[					// track points
          {
            "distance": 0,				// track distance (meters)
            "elevation": 1.1,				// track elevation (meters)
            "latitude": 19.64027,			// track latitude
            "longitude": -155.99675			// track longitude
          },
          {
            "distance": 10.712,
            "elevation": 1.4,
            "latitude": 19.64027,
            "longitude": -155.99675
          }
      ],
      "segments":[					// segments
          {
            "segment_count": 1,				// segment count
            "distance": 1885.315,			// segment distance (meters)
            "start_latitude": 19.64021,			// segment start latitude
            "end_latitude": 19.64867,			// segment end latitude
            "start_longitude": -155.99683,		// segment start longitude
            "end_longitude": -156.00451,		// segment end longitude
            "start_elevation": 1.1,			// segment start elevation (meters)
            "end_elevation": 13.7,			// segment end elevation (meters)
            "bearing": 319.472,				// segment bearing (degrees)
            "grade": 0.668,				// segment grade (percent)
            "time": 187.4369,				// segment time (seconds)
            "speed": 10.284,				// segment speed (meters/second)
            "average_speed": 10.093,			// segment average speed (meters/second)
            "power": 305,				// segment power (watts)
            "percent_ftp": 0.837,			// segment percent of ftp (percent)
            "yaw_angle": 7.48,				// segment yaw angle (degrees)
            "drag_effect": 0.3913,			// segment drag (cda)
            "wind_effect": -1.262,			// segment wind effect (meters/second)
            "air_density": 1.0914,			// segment air density (kg/m^3)
            "rolling_resistance": 0.0056,		// segment rolling resistance 
            "bike_weight": 9.98,			// segment bike weight (kilograms)
            "rider_weight": 74.84			// segment rider weight (kilograms)
          },
          {
            "segment_count": 2,
            "distance": 101.619,
            "start_latitude": 19.64867,
            "end_latitude": 19.64942,
            "start_longitude": -156.00451,
            "end_longitude": -156.00396,
            "start_elevation": 13.7,
            "end_elevation": 14.2,
            "bearing": 34.630,
            "grade": 0.492,
            "time": 10.4397,
            "speed": 9.902,
            "average_speed": 9.734,
            "power": 309,
            "percent_ftp": 0.865,
            "yaw_angle": 8.19,
            "drag_effect": 0.3902,
            "wind_effect": 0.793,
            "air_density": 1.0923,
            "rolling_resistance": 0.0056,
            "bike_weight": 9.98,
            "rider_weight": 74.84	
          }
      ]     
    }
  ]
}

Race Details Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes
race_id
integer
Specifies the exact race to pull. Yes

Race Plan Update

The following demonstrates how to update a specific race plan with new parameters.

Sample Request

You can request a race plan update by sending parameters in the post parameters and receive the updated race details in the response.

Header Parameters

authorization: xxxxxxxxxxxxxxxxxx

POST Resource URL

https://www.bestbikesplit.com/api/v1/race-update

POST Parameters

race_id=164
model_type=1
goal_watt=325

Sample Response

Race's detailed information returned as JSON for the race with the specific id passed as race_id in the request parameters.

See above Race Plan Details for response example.

Race Parameters

Parameter Description Required
authorization
A unique token to authorize use of the Best Bike Split API. Yes
race_id
integer
Specifies the exact race to update. No
model_type
integer
Set the model type to be used. (range: 1 to 3)
1 = Normalized Power Model
2 = Goal Time Model
3 = Training Stress Score Model
No
Please note that one of the following three parameters is required if a model_type is requested and is dependent on the model_type.
goal_watt
integer
Goal normalized power target in watts. No
goal_time
integer
Goal finish time in seconds. No
goal_tss
integer
Goal target training stress score. No
rider_weight
float
Rider's weight in kilograms. (range: 30 to 150, up to 2 decimal places) No
bike_weight
float
Bike's weight in kilograms. (range: 4 to 25, up to 2 decimal places) No
ftp
integer
Rider's functional threshold power in watts. No
race_drag
float
Drag coefficient for 0° yaw in a racing position. (up to 4 decimal places) No
climb_drag
float
Drag coefficient for 0° yaw in a climbing position. (up to 4 decimal places) No

Error Codes

The Best Bike Split API uses the standard set of HTTP response codes. For convenience, the most relevant ones are listed here.

Note that, in the event of an error, a message is returned in the response body.

Code Type Description
200 OK Success!
400 Bad Request The request could not be understood due to malformed syntax.
401 Unauthorized Authentication credentials were missing or incorrect.
403 Forbidden The request is understood but it has been refused due to insufficient permission.
404 Not Found The URI requested is invalid or the resource requested, such as a user, does not exist.
405 Method Not Allowed The URI requested does not support the specific HTTP method used in the request.
500 Internal Server Error Something is broken. Please contact us so our support team can investigate.
502 Bad Gateway The server is down or being upgraded.
503 Service Unavailable The servers are up, but overloaded with requests. Try again later.