A tool to sync Wahoo bike rides into Garmin Connect.
This application will be triggered by the Wahoo API each time a new activity is registered on its platform.
The webhook will then upload the .fit
file to Garmin Connect.
- You need to register an app at Wahoo Developer Portal
- With scope:
email power_zones_read workouts_read plans_read routes_read offline_data user_read
- Choose Sandbox (it will be approved more quickly) and enable Webhook.
- With Webhook URI to:
https://your_website_url.com/webhook
This application should be accessible behind this domain.
Inside the wahoo_garmin_sync
directory:
- Replace the placeholders GARMIN_LOGIN and GARMIN_PASSWORD in the
docker-compose.yml
file with your Garmin Connect login credentials. - Then run the following command:
docker compose up --build -d
- Open a browser and and navigate to http://localhost:42195 or https://your_website_url.com
You should see a simple ok message.
When the application is triggered by the Wahoo webhook, the logs (viewable with docker logs wahoo
) should look like this:
Received post
Workout url: https://cdn.wahooligan.com/wahoo-cloud/production/uploads/workout_file/file/jxre2UP3Lx_o6wF-8tdArw/2025-01-06-171681-ELEMNT_ROAM_F23E-852-0.fit
Filename: 2025-01-06-171681-ELEMNT_ROAM_F23E-852-0.fit
192.168.1.23 - - [06/Jan/2025 18:19:52] "POST /webhook HTTP/1.1" 200 -
File saved
Connected to _Garmin Connect_
{'detailedImportResult': {'uploadId': 302033637404, 'uploadUuid': {'uuid': 'eafa3083-3c1a-4529-bd59-f298f06418e4'}, 'owner': 166921955, 'fileSize': 85828, 'processingTime': 564, 'creationDate': '2025-01-06 18:19:56.336 GMT', 'ipAddress': None, 'fileName': '2025-01-06-171681-ELEMNT_ROAM_F23E-852-0.fit', 'report': None, 'successes': [], 'failures': []}}
Workout successfully uploaded
The Bruno collection contains:
- Garmin request to upload manually a file to Garmin Connect
- Fill the token value with the access_token value.
Can be found by running:docker exec -it wahoo sh cat ~/.garth/oauth2_token.json
- Choose the
.fit
file to upload
- Fill the token value with the access_token value.
- Webhook request to call the deployed
/webhook
endpoint- Filename can be found by listing workouts with the Wahoo API
- To receive a token:
You will be redirected to your application with this url, holding a code:
curl https://api.wahooligan.com/oauth/authorize?client_id=<client_id>&redirect_uri=https://your_website_url.com&scope=email%20power_zones_read%20workouts_read%20plans_read%20routes_read%20offline_data%20user_read&response_type=code -H "Content-Type: application/json"
Use it to the run:https://your_website_url.com/?code=<code>
Response:curl -X POST https://api.wahooligan.com/oauth/token?client_secret=your_client_secret&code=<code>&redirect_uri=https://your_website_url.com&grant_type=authorization_code&client_id=<client_id> -H "Content-Type: application/json"
Use the access_token value (it expires after 2 hours){"access_token":"<access_token>","token_type":"Bearer","expires_in":7199,"refresh_token":"<refresh_token>","scope":"email power_zones_read workouts_read plans_read routes_read offline_data user_read","created_at":1736182705,"user_id":4112422}