Conversation
The activity search endpoint and pagination loop fetched ALL activities on every sync regardless of date range. For a user with 3,500+ activities this meant 35+ API calls just for the activity list on a 1-day incremental sync. Add startDate/endDate params to the activity search URL so only activities within the requested range are fetched. Fixes #23
There was a problem hiding this comment.
Pull request overview
This PR fixes excessive activity-list pagination by applying the requested startDate/endDate date range filter to Garmin’s activity search endpoint, so incremental/range syncs no longer page through a user’s entire activity history.
Changes:
- Add
startDate/endDateto the initial activities search URL returned byfull_range_rest(). - Apply the same date filtering to the activities pagination loop in
GarminClient.fetch_all(). - Apply the same date filtering to the activity-ID fallback query used for per-activity detail fetching.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
garmin_client/endpoints.py |
Adds date-range query params to the base activities search endpoint returned for full-range fetches. |
garmin_client/client.py |
Updates activity pagination and activity-ID fallback query to respect the same startDate/endDate filter. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
garmin_client/client.py
Outdated
| try: | ||
| act_data = self.api_fetch( | ||
| "/gc-api/activitylist-service/activities/search/activities?limit=1000&start=0" | ||
| f"/gc-api/activitylist-service/activities/search/activities?limit=1000&start=0&startDate={s_date}&endDate={e_date}" | ||
| ) |
There was a problem hiding this comment.
The activity-ID fallback query is capped at limit=1000 with no pagination. If the requested date range contains more than 1000 activities, activity_ids will be incomplete and per-activity detail endpoints (splits/HR zones/weather) won’t be fetched for activities beyond the first 1000. Consider paginating this fallback (same start += limit loop used for the main activity list) or collecting IDs during the existing pagination loop so detail fetching always covers the full range.
garmin_client/client.py
Outdated
| # 2b. Paginate remaining activities within the date range | ||
| page_start = 100 | ||
| while True: | ||
| act_result = self._fetch_batch( | ||
| { | ||
| f"activities_page_{page_start}": f"/gc-api/activitylist-service/activities/search/activities?limit=100&start={page_start}" | ||
| f"activities_page_{page_start}": f"/gc-api/activitylist-service/activities/search/activities?limit=100&start={page_start}&startDate={s_date}&endDate={e_date}" | ||
| }, |
There was a problem hiding this comment.
The activities search URL is now duplicated in multiple places (endpoints.py initial page, fetch_all pagination, and the activity-ID fallback), including repeated constants like limit=100 and the date filter params. This increases the chance of future drift (e.g., changing limit or adding params in one place but not the others). Consider factoring a small helper to build the activities search URL from start/limit/startDate/endDate and reuse it in all three call sites.
--latest previously only worked with --fit-only. Now it also works as a standalone flag to fetch only today's data, which is what users expect when they run garmin-givemydata --latest. Fixes #23
…cation Single source of truth for the activities search URL with date filtering, limit, and offset params. Used in endpoints.py, the pagination loop, and the activity ID fallback.
Summary
startDateandendDateparams to the activity search endpoint so only activities within the requested range are fetched--latestwork for regular syncs — fetches only today's dataProblem
Every sync — even a 1-day incremental — paginated through all activities the user has ever recorded. For a user with 3,500+ activities (Full-range data #23), this meant 35+ API calls just for the activity list.
--latestonly worked with--fit-only. Runninggarmin-givemydata --latestignored the flag and did a full sync, which is not what users expect.What changed
endpoints.py:full_range_rest()now passesstartDate/endDateto the activities search URLclient.py: pagination loop and activity ID fallback both include the date filtergarmin_givemydata.py:--latestwithout--fit-onlynow sets the date range to today onlyHow to test
git clone https://github.com/nrvim/garmin-givemydata.git cd garmin-givemydata git checkout fix/incremental-activity-pagination bash setup.shIf you already have a database with data:
Before this fix you'd see dozens of
Activities page: fetched 100 more (offset ...)lines. After the fix, you should see zero (or just a few if you had many activities that day).Fixes #23