The Strava API has a call to retrieve the first 50 efforts for a segment. In theory, the API supports an offset parameter to allow you to download additional efforts after the first 50. However the offset parameter does not work currently in the segment efforts API. I didn’t want to wait until V3 of the API, so…
Additionally, the segment efforts API returns efforts ordered fastest to slowest, so a naive date-based retrieval does not work, and this may also be why the offset parameter is not currently supported.
I now have a workaround which does the job (albeit a little more slowly): use the startDate and endDate parameters, which do work, to initially pull the efforts across “all time” (or, say, from 2010 to now). If you receive 50 efforts back from the call, then split the time window in half, and retrieve each half. Rinse and repeat until you receive less than 50 efforts for a window, at which point you know you have all the efforts for that window. It’s simple enough to merge the arrays that you receive in response.
This works fine, but is a bit more load on the Strava servers. For example, a segment with 425 efforts required 28 calls as opposed to 9 if the offset parameter worked, or just 1 if you could request the full set of efforts (which is still not a huge download, although really busy segments may be a bit more problematic).
I now optimise to retrieve all efforts for segments just once, then just the last few days worth later on. The downside is that new subscribers will not have old efforts uploaded (to resolve this I may periodically do the full sync again). New segments would also bump into this issue until a global sync is done.
My implementation is not perfect (I’m ignoring errors for now), and if there are 50 efforts in less than 1 second then I’ll get none of them 🙂 Nevertheless, this little PHP code snippet is one way it could be done.
if($startDate == 0 && $endDate == 0)
$startDate = mktime(0,0,0,1,1,2010);
$endDate = time();
if($startDate >= $endDate) return null;
$startDateString = date(“Y-m-d\\TH:i:s\\Z”, $startDate);
$endDateString = date(“Y-m-d\\TH:i:s\\Z”, $endDate);
$efforts = $this->callApi(“/v1/segments/$segmentId/efforts?startDate=$startDateString&endDate=$endDateString”);
$numEfforts = sizeof($efforts->efforts);
if($numEfforts == 50)
// split the time period in 2
$midDate = round(($startDate + $endDate) / 2, 0);
$firstEfforts = $this->getSegmentEfforts($segmentId, $startDate, $midDate);
$secondEfforts = $this->getSegmentEfforts($segmentId, $midDate, $endDate);
if($firstEfforts == null) return $secondEfforts;
if($secondEfforts == null) return $firstEfforts;
$firstEfforts->efforts = array_merge($firstEfforts->efforts, $secondEfforts->efforts);