CarStat.dev
Connect key
Guide

Sync the full inventory

/cars streams every active car in your sources, with full reports, through a server-side cursor. Use it to keep a local copy; use /search only for user-facing queries.

GET /carslimit up to 2000, no scroll_id
store data[]upsert by id, skip if hash is unchanged
GET next_urlunchanged, before the cursor expires
scroll_id nullpass complete
archivecars not seen in this pass
  1. Start a passRequest /cars without scroll_id. Set filters such as domains[] or is_leasing only here.
  2. Follow next_url exactlyKeep the same key and filters for the whole pass. Changing domains[] or is_leasing mid-scroll returns 422.
  3. Fetch before the cursor expiresscroll_time is 1–15 minutes (default 10), counted from the last request. On 403/404 with "scroll id was expired", start a new pass.
  4. Finish, then archiveThe pass ends when scroll_id is null and data is empty. Only then mark cars you didn't see as sold.

Run a full pass 2–3 times a day. Archived cars leave /search and /cars right away, but stay reachable through /cars/{car_id} and /listing/{domain_id}/{listing_id} with archived: true for about a month.

Full export loop
url="https://api.lotarius.com/cars?limit=2000&api_key=$CARS_API_KEY"

while [ -n "$url" ]; do
  page=$(curl -sfg "$url" -H "Accept: application/json") || { echo "cursor expired, restart"; exit 1; }
  echo "$page" | jq -c '.data[]' >> cars.ndjson
  url=$(echo "$page" | jq -r '.next_url // empty')
done
Last pageLive
{
  "scroll_id": null,
  "data": [],
  "total": 3217391,
  "message": "No more data"
}