github cyberjunky/python-garminconnect 0.3.18
Releas 0.3.18

2 hours ago

What's Changed

Added

  • Jet Lag Adviser trips: new get_jetlag_trips(), add_jetlag_trip(), update_jetlag_trip() and delete_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:00 and +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 the hasImages flag in get_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() and create_strength_timed_set() for exercises done for time (planks, carries). Every strength helper also accepts an optional description, 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 optional skip_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.typed marker, 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 like 1.9 and "1.9" are now rejected before any request is sent. Integers, "123" and 123.0 still 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.md and a changelog (CHANGELOG.md). The login-strategy diagnostic script moved to scripts/test_strategy.py. (#469)

Thanks

Full Changelog: 0.3.17...0.3.18

Don't miss a new python-garminconnect release

NewReleases is sending notifications on new releases.