What's Changed
Added
- Jet Lag Adviser trips: new
get_jetlag_trips(),add_jetlag_trip(),update_jetlag_trip()anddelete_jetlag_trip(). Tested live on a real account, including multi-leg trips in both directions, trips in the past, and a start date before the first flight. Garmin doesn't look up locations, so each place needs its UTC offset on that date (between-12:00and+14:00), and each time is the local time at that place, without an offset. (#457) - Activity photos: new
get_activity_images(activity_id)returns the photos attached to an activity as a list of{imageId, url, photoDate}, or[]when there are none. The URLs expire after 24 hours, and thehasImagesflag inget_activities()results isn't a reliable sign that an activity has photos. (#454, #455) - Timed strength exercises and per-step notes: new
create_strength_timed_step()andcreate_strength_timed_set()for exercises done for time (planks, carries). Every strength helper also accepts an optionaldescription, a per-step note such as a form cue. Tested live: Garmin stores the time-based steps and the descriptions as sent. (#458, #466) - Swim CSS offset targets: new
SwimCssOffsetTarget(offset_seconds=...)sets a pace target relative to your Critical Swim Speed, as the secondary target. The targeted step helpers now also accept a secondary target without a primary one. Tested live: Garmin Connect shows the step as CSS +5s. (#456) - Skip the last rest in a repeat:
create_repeat_group()takes an optionalskip_last_rest_step, which leaves out the final rest of a repeat group. Works fully on newer watches (roughly FR955 and later). (#452) - Type information: the package now ships a
py.typedmarker, so mypy and other type checkers use its annotations. (#469) - Python 3.14 is now tested in CI. (#469)
- Demo: new menu entries for jet lag trips (Hydration & Wellness), activity photos (Activities & Workouts), and sample uploads for swim CSS targets and timed strength sets. The two sample uploads read the workout back to show what Garmin stored.
Fixed
- IDs are no longer silently rounded down: every method that takes an ID (activities, workouts, devices, weigh-ins, trips, training plans, golf scorecards) used to cut off anything after the decimal point, so
delete_activity(1.9)would have deleted activity 1. Values like1.9and"1.9"are now rejected before any request is sent. Integers,"123"and123.0still work. (#465) - Clearer error when the API refuses a call after login: when the test call made after login gets a 403, the "token rejected by API tier" error now notes that a 403 can mean Garmin is blocking your client or network, not rejecting your token. A 401 (an actually refused token) is unchanged. The status is also read more reliably from the error, so a server error whose text happens to mention "403" no longer counts as a rejected token. (#444, #467)
- API error responses are no longer logged: when an API call fails, the debug log now records only the status code, not the full response body, which could contain account or session details. (#464)
- Token exchange errors are no longer logged: when the login token exchange fails, the debug log records only the status code, not Garmin's error response. (#468)
- Demo: the HTML health report's Step Goal card now actually shows, filled from the daily summary. (#462)
Docs
- The Authentication section now says that login uses the iOS app's client ID (
GCM_IOS_DARK), not the Android one, and the token exchange is described as it actually happens. (#461) - README method counts updated to 164+ across 14 categories.
- Fixed formatting in a README code example that newer ruff versions flagged, which had been failing CI. (#463)
- New
CONTRIBUTING.mdand a changelog (CHANGELOG.md). The login-strategy diagnostic script moved toscripts/test_strategy.py. (#469)
Thanks
- @aaronspruit for the Jet Lag Adviser methods (#457), tested live across every edge case Garmin accepts.
- @cpruijsen for
get_activity_images()(#455). - @fasoxy-it for the swim CSS offset target (#456).
- @MartinDejmal for
skip_last_rest_step(#452). - @danihrndzld for the authentication docs fix (#461) and the demo Step Goal card fix (#462).
- @mukhtadir-syed for the detailed, live-tested report behind the timed strength steps and per-step notes (#458).
Full Changelog: 0.3.17...0.3.18