API Docs

Delta polling & pagination

Syncing loads on a schedule — updatedSince, page math, and the one caveat that matters.

The sync recipe

Most integrations poll once or twice a day. The recommended loop:

  1. Call GET /api/v1/loads?updatedSince=<cursor>&page=1&pageSize=1000.
  2. Follow hasMore through the pages, upserting each row into your system keyed by loadNumber.
  3. Track the maximum updatedAt you've seen across the sweep.
  4. Next run, set updatedSince to that maximum minus a small overlap (5 minutes is plenty). Duplicates are harmless because you're upserting.
curl -H "Authorization: Bearer $KEY" \
  "https://www.fr8factory.com/api/v1/loads?updatedSince=2026-07-09T18:55:00Z&pageSize=1000"

How updatedSince behaves

  • Only loads with updatedAt >= updatedSince return.
  • updatedAt moves only on real value changes. Our internal sync machinery re-checks loads against our TMS every few minutes, but a re-check that changes nothing does not touch updatedAt — so your delta stays quiet when nothing happened.
  • Accepts an ISO 8601 date (2026-07-01) or datetime (2026-07-01T00:00:00Z). Unparseable values get a 400 with details.

Pagination

  • page is 1-based; pageSize defaults to 100 and accepts up to 1000 (larger values clamp to 1000).
  • The envelope carries page, pageSize, totalCount, and hasMore.
  • Rows are stably ordered by (updatedAt, id) ascending, so a page boundary always falls at the same place for a fixed dataset.

The page-skew caveat

Page-number pagination over live data has one inherent hazard: if a load is updated while you're mid-sweep, rows can shift between pages — its updatedAt changes, which moves it later in the sort order. In the worst case a row you haven't fetched yet moves behind your cursor and that sweep misses it. (Rows can also duplicate across pages, which your upsert already absorbs.)

You don't need to solve this in-sweep. The overlap in step 4 of the recipe is the fix: anything that moved mid-sweep has, by definition, a fresh updatedAt, so it's guaranteed to appear in your next poll's delta. With an overlapped updatedSince and loadNumber upserts, the loop is self-healing — a missed row stays missing for at most one poll interval.

If you're doing a one-time full backfill and want it airtight, run the sweep, then immediately re-query with updatedSince set to the time the sweep started. The second pass picks up anything that moved.

On this page