Pagination
Offset paging with a hard ceiling, and the cursor-based sync feed for when you need every record.
GET /projects/search pages with limit and offset. limit is capped at 100 records per page; asking for more is clamped and the response says so in meta.warnings rather than failing.
The honest ceiling
In practice this only bites on very broad queries. The answer is not deeper paging, it is narrowing — by geography, by date window, or by a measurement bound — and counting each narrowed variant for free until the total is one you can actually retrieve.
When you need every record: use sync
Offset paging over a changing dataset can skip records: if a record is updated and re-sorts while you are on page 4, you can miss it. GET /projects/sync walks by cursor in last-updated order, which makes it lossless, and it refuses sort, order, offset and page because a caller-chosen ordering would break that guarantee while appearing to work.
One net-new record and one that changed since you last saw it
curl 'https://api.boardwalkai.com/api/v1/projects/sync?states=UT&representation=compact&limit=2' \
-H 'Authorization: Bearer bwk_live_YOUR_KEY'Response · HTTP 200
{
"data": [
{
"id": 184203,
"recordType": "project",
"projectName": "Alta Ridge Phase II",
"boardwalkLink": "https://boardwalkai.com/map/#project=184203",
"mergedFrom": [
184203,
184987
],
"lastUpdated": "2026-06-18T09:22:41Z",
"meetingDate": "2026-06-17",
"delivery": {
"alreadyExported": false,
"updatedSinceExport": null,
"lastExportedAt": null,
"billed": true
},
"address": "3600 S Constitution Blvd, West Valley City, UT",
"city": "West Valley City",
"county": "Salt Lake",
"state": "UT",
"latitude": 40.6916,
"longitude": -112.0011,
"propertyType": "residential",
"propertyTypeLabel": "Residential",
"status": "approved_with_conditions",
"statusLabel": "Approved with Conditions"
},
{
"id": 191774,
"recordType": "project",
"projectName": "Foothill Commons",
"boardwalkLink": "https://boardwalkai.com/map/#project=191774",
"mergedFrom": [
191774
],
"lastUpdated": "2026-06-24T14:08:03Z",
"meetingDate": "2026-06-23",
"delivery": {
"alreadyExported": true,
"updatedSinceExport": true,
"lastExportedAt": "2026-07-19T02:14:55Z",
"billed": true
},
"address": null,
"city": "Provo",
"county": "Utah",
"state": "UT",
"latitude": 40.2338,
"longitude": -111.6585,
"propertyType": "residential",
"propertyTypeLabel": "Residential",
"status": "continued",
"statusLabel": "Continued"
}
],
"meta": {
"schemaVersion": "2026-08-02",
"representation": "compact",
"limit": 2,
"creditsUsed": 2,
"creditsRemaining": 284,
"delivery": {
"mode": "all",
"notPreviouslyExported": 1,
"previouslyExported": 1,
"updatedSinceExport": 1,
"billed": 2,
"notRebilled": 0,
"ledgerApplied": true
},
"cursor": "eyJ1cGRhdGVkQXQiOiIyMDI2LTA4LTAyVDE0OjA5OjIyWiIsImlkIjoxOTE3NzR9",
"hasMore": true
}
}Record bodies on this page were produced by running Boardwalk's production response mapper over a documented sample project, so the field set, the labels and the empty fields are exactly what the API emits. The project itself is a sample, not a real filing.
Carry meta.cursor into the next request and stop when hasMore is false. A cursor is only valid for the filter set and entitlement scope it was minted for; using it with a different query returns 400 invalid_cursor rather than quietly walking the wrong set.
Ready to make a call?
A free Boardwalk trial includes API access and a sandbox key. Counting, filtering, the location tree and the analytics plane cost nothing, so you can evaluate the data before you spend a credit.