iRacing's Recent Races Endpoint Only Ever Returns Ten
member_recent_races caps at 10 per driver, so a new member looks like a rookie forever. Backfilling means a different endpoint — and a position convention that flips.
I run the results archive for a sim racing team — every race the team enters, per driver, with career totals and a record book on top. The collector sweeps iRacing’s data API every thirty minutes and upserts what it finds.
Then the team grew, and the new drivers all looked like they’d barely raced.
The cap
stats/member_recent_races returns the last ten races for that member.
Never more. There’s no paging parameter, no offset, no date range that widens
it. Ten is the endpoint.
That’s fine for a driver you’ve been sweeping for months — my own row count was in the hundreds, but only because half a year of thirty-minute polls had accumulated history the endpoint never would have handed over in one go. Every newly added member starts permanently stuck at ten, and stays there until they race an eleventh time, at which point the first one falls off the end.
So the collector wasn’t broken. It was doing exactly what it was told, and the data model quietly depended on having been running since before the drivers joined. That’s a nasty property: it works perfectly in production and fails for every new member, forever.
Backfilling means a different endpoint
The history does exist, via results/search_series — full official-series
results for a cust_id, requested one season_year + season_quarter at a
time, with event_types=5 and official_only=true.
Two structural differences from the recent-races endpoint:
- The response is not the data. You get
{"data": {chunk_info}}pointing at pre-signed S3 chunk files, which you then fetch without your auth cookie. Same pattern asresults/lap_data. - You have to know which quarters to ask for. Scanning every quarter since the driver joined mostly returns nothing. Their yearly stats give you the years with starts greater than zero, so you only walk the quarters that can contain something.
The trap that makes the data look wrong
This one cost me the most, because it produces plausible numbers rather than obvious errors:
search_series returns positions that are 0-based and measured against the
overall field. member_recent_races returns 1-based, in-class.
Both. At once. So a multi-class race where a driver finished ninth in GT3 comes
back from one endpoint as 9 and from the other as 20 — and if you write
both into the same column, that driver’s average finish and podium count are
now silently wrong, and wrong in a direction that depends on which endpoint
happened to supply each row.
The conversion is finish_position_in_class + 1 and
starting_position_in_class + 1 on the search rows. I only caught it by
backfilling a subsession that the sweep had already collected and diffing the
two versions of the same race. If you’re stitching two endpoints together, find
an overlapping record and compare it field by field before you trust the merge.
What each endpoint knows
They’re not the same shape either, which matters if you’re upserting one over the other:
search_seriesrows do carrycar_name,license_category,starting_positionand a nestedtrack.config_name— fields the recent-races endpoint leaves empty.- They don’t carry
oldi_rating/newi_rating/sub_level, which come back asNone. Historical rows therefore have no iRating or Safety Rating delta, and never will. - The timestamp is
start_time, notsession_start_time.
Because each endpoint fills gaps the other leaves, the upsert has to merge
rather than replace — ON CONFLICT with COALESCE per column, so a backfill
enriches an existing row instead of blanking the ratings the live sweep
captured.
One more: results/lap_data returns 400 for some older subsessions. iRacing
doesn’t keep lap data forever. Treat it as a skip, not a failure, or a
backfill across several seasons will die partway through.
The general shape
An endpoint named “recent” is telling you something. When it’s the only source you have and your dataset looks complete, that’s usually because time has been quietly doing the paging for you — and it will not do the same favour for the next record you add.
I’m Chris Moore — an independent developer and consultant in Henderson, NV, working under Grudged LLC. I build data pipelines and the reporting on top of them, including the results platform behind a sim racing team. If an API is giving you less than you think it is, get in touch.