Install
openclaw skills install concept2Fetch and analyze Concept2 Logbook workout data via API with pulse zone analysis and trend tracking. Use when the user wants to retrieve rowing/skiing/biking...
openclaw skills install concept2Fetch and analyze workout data from Concept2 Logbook with advanced pulse zone and trend analysis.
Use the provided script to fetch workouts:
python3 scripts/fetch_workouts.py --token <API_TOKEN> --from-date 2026-03-01 --format table
Requires a Concept2 API access token. Get one from: https://log.concept2.com/developers/keys
Token must be passed with Authorization: Bearer <token> header.
| Endpoint | Description |
|---|---|
GET /api/users/me | Get authenticated user info |
GET /api/users/me/results | Get workouts (paginated) |
GET /api/users/me/results/{id} | Get specific workout |
GET /api/users/me/results/{id}/strokes | Get stroke-level data |
| Param | Type | Description |
|---|---|---|
from | date | Start date (YYYY-MM-DD) |
to | date | End date (YYYY-MM-DD) |
type | string | Workout type: rower, skierg, bike, etc. |
per_page | integer | Results per page (max 250) |
| Type | Description |
|---|---|
| JustRow | Free rowing |
| FixedDistanceSplits | Fixed distance with splits |
| FixedTimeSplits | Fixed time with splits |
| FixedCalorie | Fixed calorie target |
| FixedWattMinute | Fixed watt-minute target |
| FixedTimeInterval | Time-based intervals |
| FixedDistanceInterval | Distance-based intervals |
| FixedCalorieInterval | Calorie intervals |
| FixedWattMinuteInterval | Watt-minute intervals |
| VariableInterval | Variable intervals |
| VariableIntervalUndefinedRest | Variable with undefined rest |
| Type | Description |
|---|---|
| rower | RowErg |
| skierg | SkiErg |
| bike | BikeErg |
| dynamic | Dynamic RowErg |
| slides | RowErg with slides |
| paddle | PaddleErg |
| water | WaterRower |
| snow | Snow (Nordic skiing) |
| rollerski | Roller skiing |
| multierg | MultiErg |
# Auto-detect max HR from birthdate in profile
python3 scripts/fetch_workouts.py --token <TOKEN> --from-date 2026-03-01
# Specify max HR manually
python3 scripts/fetch_workouts.py --token <TOKEN> --max-hr 165 --from-date 2026-02-01
# Estimate max HR from age
python3 scripts/fetch_workouts.py --token <TOKEN> --age 59 --from-date 2026-02-01
python3 scripts/fetch_workouts.py --token <TOKEN> --trends 8 --from-date 2026-01-01
# Simple table
python3 scripts/fetch_workouts.py --token <TOKEN> --format table
# JSON export
python3 scripts/fetch_workouts.py --token <TOKEN> --format json > workouts.json
# Filter by equipment type
python3 scripts/fetch_workouts.py --token <TOKEN> --type skierg
Zones based on percentage of maximum HR:
| Zone | Name | Range | Purpose |
|---|---|---|---|
| 🟢 1 | Restitusjon | 0-60% | Recovery, warmup |
| 🔵 2 | Aerob kapasitet | 60-70% | Base building |
| 🟡 3 | Aerob effekt | 70-80% | Tempo training |
| 🟠 4 | Anaerob terskel | 80-90% | Threshold/intervals |
| 🔴 5 | Maks kapasitet | 90-100% | VO2max/sprints |
--max-hr 165--age 59 (uses Tanaka formula: 208 - 0.7×age)Weekly aggregation of:
The script provides personalized tips:
pace_tenths = (time_tenths / distance_m) * 500
total_seconds = time_tenths / 10
minutes = int(total_seconds // 60)
seconds = total_seconds % 60
formatted = f"{minutes}:{seconds:04.1f}"
| Code | Meaning | Resolution |
|---|---|---|
| 200 | OK | Success |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Check request format |
| 401 | Unauthorized | Invalid or expired token |
| 403 | Forbidden | User hasn't authorized app |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate entry |
| 422 | Unprocessable | Validation error |
| 500 | Server Error | Try again later |
| 503 | Service Unavailable | API temporarily down |
Paginated responses include a meta.pagination object:
{
"meta": {
"pagination": {
"total": 150,
"count": 50,
"per_page": 50,
"current_page": 1,
"total_pages": 3,
"links": {
"next": "https://log.concept2.com/api/users/me/results?page=2"
}
}
}
}
Default per_page is 50, maximum is 250.