@@ -40,20 +40,20 @@ Make your selection:
4040
4141## API Coverage Statistics
4242
43- - ** Total API Methods** : 131 + unique endpoints (snapshot)
43+ - ** Total API Methods** : 134 + unique endpoints (snapshot)
4444- ** Categories** : 13 organized sections
4545- ** User & Profile** : 4 methods (basic user info, settings)
4646- ** Daily Health & Activity** : 9 methods (today's health data)
4747- ** Advanced Health Metrics** : 12 methods (fitness metrics, HRV, VO2, training readiness, running tolerance)
4848- ** Historical Data & Trends** : 9 methods (date range queries, weekly aggregates)
49- - ** Activities & Workouts** : 36 methods (comprehensive activity, workout management, typed workout uploads, scheduling, import)
49+ - ** Activities & Workouts** : 38 methods (comprehensive activity, workout management, typed workout uploads, scheduling, import, edit description / exercise sets )
5050- ** Body Composition & Weight** : 8 methods (weight tracking, body composition)
5151- ** Goals & Achievements** : 15 methods (challenges, badges, goals)
5252- ** Device & Technical** : 7 methods (device info, settings)
5353- ** Gear & Equipment** : 7 methods (gear management, tracking)
5454- ** Hydration & Wellness** : 12 methods (hydration, nutrition, blood pressure, menstrual)
5555- ** System & Export** : 4 methods (reporting, logout, GraphQL)
56- - ** Training Plans** : 2 methods
56+ - ** Training Plans** : 3 methods (plans, plan by ID, adaptive plan by ID)
5757- ** Golf** : 3 methods (scorecard summary, scorecard detail, shot data)
5858
5959### Interactive Features
@@ -166,6 +166,29 @@ No browser is needed.
166166~ /.garminconnect/garmin_tokens.json # saved automatically, mode 0600
167167```
168168
169+ ** Resilient login (multi-strategy + token validation):**
170+
171+ ` login() ` tries several authentication strategies in order (mobile, SSO widget,
172+ web portal — each with and without TLS impersonation) and only declares success
173+ when the resulting token is actually accepted by the API. If a strategy obtains
174+ a token the API later rejects (a region/account-specific condition — see
175+ [ #369 ] ( https://github.com/cyberjunky/python-garminconnect/issues/369 ) ), the
176+ library transparently falls through to the next strategy. Set
177+ ` Garmin(..., verify_login=False) ` to restore the legacy "first token wins"
178+ behavior.
179+
180+ ** Cached-token gotcha & self-healing:** when a ` tokenstore ` is supplied,
181+ ` login() ` loads those tokens * before* the strategy chain and short-circuits if
182+ they load — so stale/poisoned cached tokens used to fail every run. The library
183+ now detects this: if cached tokens are rejected by the API, it discards them and
184+ performs a fresh credential login automatically. To force a clean slate yourself
185+ (e.g. between a failed resume and a retry), call:
186+
187+ ``` python
188+ g.logout() # clears in-memory auth + cached tokens (uses GARMINTOKENS)
189+ g.logout(tokenstore) # or pass an explicit path
190+ ```
191+
169192## 🧪 Testing
170193
171194Run ` example.py ` once first to create saved tokens in ` ~/.garminconnect ` , then:
0 commit comments