A Home Assistant Add-On that exposes a local REST API for creating and scheduling Garmin Connect workouts.
The Node.js API wraps the python-garminconnect library, keeping Garmin API calls to a minimum through session caching.
- In Home Assistant, navigate to Settings → Add-ons → Add-on Store.
- Click the ⋮ menu → Repositories and add the URL of this repository.
- Find Garmin Connect in the list and click Install.
After installation, configure the add-on under the Configuration tab:
| Option | Description |
|---|---|
garmin_email |
Your Garmin Connect account e-mail |
garmin_password |
Your Garmin Connect account password |
api_port |
Port the REST API listens on (default: 8099) |
Credentials are stored in Home Assistant's add-on options (encrypted at rest).
The OAuth session token is cached in /data/garth so subsequent API calls do not require re-authentication.
Base URL: http://<ha-host>:<api_port>
GET /api/workouts
POST /api/workouts/intervals
Content-Type: application/json
Body:
{
"name": "5x400m Intervals",
"warmup": { "type": "distance", "value": 1000 },
"intervals": {
"repetitions": 5,
"work": {
"type": "distance",
"value": 400,
"target": { "type": "pace", "min": "4:30", "max": "5:00" }
},
"rest": { "type": "time", "value": 90 }
},
"cooldown": { "type": "distance", "value": 1000 },
"scheduleDate": "2024-08-15"
}Fields with type accept "distance" (metres) or "time" (seconds).
scheduleDate is optional — if supplied, the workout is scheduled immediately after creation.
target is optional and supports:
{ "type": "pace", "min": "MM:SS", "max": "MM:SS" }— pace per km{ "type": "heartRate", "min": <bpm>, "max": <bpm> }
POST /api/workouts/endurance
Content-Type: application/json
Body:
{
"name": "Easy Long Run",
"duration": { "type": "distance", "value": 12000 },
"target": { "type": "heartRate", "min": 130, "max": 150 },
"warmup": { "type": "distance", "value": 1000 },
"cooldown": { "type": "distance", "value": 1000 },
"scheduleDate": "2024-08-18"
}POST /api/workouts/:workoutId/schedule
Content-Type: application/json
{ "date": "2024-08-20" }
ha-garmin/
├── config.yaml # Home Assistant Add-On manifest
├── Dockerfile # Alpine + Python 3 + Node.js 18+
├── run.sh # Entry point (bashio config -> env vars -> node server.js)
├── scripts/
│ ├── garmin.py # Python CLI: create-workout / schedule-workout / list-workouts
│ └── requirements.txt
└── api/
├── server.js # Express app + route mounting
├── garminClient.js # Subprocess wrapper (injectable runner for testing)
├── workouts/
│ ├── base.js # Garmin step/workout builders, paceToMs()
│ ├── intervals.js # Interval builder + Express router
│ └── endurance.js # Endurance builder + Express router
└── test/
├── garminClient.test.js
├── intervals.test.js
└── endurance.test.js
Adding a new workout type requires only:
- Create
api/workouts/<type>.jswith abuild<Type>Workout()function and an Express router. - Mount the router in
server.jswithapp.use('/api/workouts/<type>', require('./workouts/<type>')).
cd api
npm install
npm test # runs 34 unit tests with Node's built-in test runner (no extra test deps)