Skip to main content

Net-new versus updated records

Pull only what you have not seen, and never pay twice for a record that has not changed.

Lead generation and business developmentData and PropTech platformsHomebuilders and developers

Who this is for

Anyone running Boardwalk on a schedule. The question is always the same: which of these did I already have, and am I paying for them again?

The answer is on every record

Delivery state is not a mode you switch on — it is a block on every record we send you, on the API and in the CSV export alike:

FieldMeaning
delivery.alreadyExportedHas this pool received this record before, through any surface?
delivery.updatedSinceExportHas it changed since then? null on a record you have never received.
delivery.lastExportedAtWhen you last received it.
delivery.billedWhether this delivery charged you for it.

Only the new ones, in one parameter

When the weekly re-run should return only leads you have never received — not your whole result set with free re-deliveries mixed in — add deliveryMode=new to the search:

bash
GET /api/v1/projects/search?states=UT&propertySubtypes=Single Family&acreageMin=100&deliveryMode=new
# meta.delivery → { "mode": "new", "excludedPreviouslyDelivered": 12, "billed": 3, ... }
Three new leads delivered and billed; the twelve you already own withheld free.

A record that changed since you received it is withheld too — you have it, and changes are the sync feed's job. all (the default) keeps returning everything with per-record delivery state disclosed.

The scheduled pull

For a mirror you keep in sync, use the sync feed rather than paging search. It walks by cursor in last-updated order, which is what makes it lossless: records that change while you are walking cannot slip past you the way they can with offset paging.

One net-new record and one that changed since you last saw it

bash
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

json
{
  "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,
      "inOpportunityZone": true,
      "inFemaFloodZone": false,
      "propertyType": "residential",
      "propertyTypeLabel": "Residential",
      "landUses": [
        {
          "type": "residential",
          "typeLabel": "Residential",
          "subtype": "multifamily",
          "subtypeLabel": "Multifamily",
          "assetClass": "Apartment Building",
          "assetClassLabel": "Apartment Building",
          "matchedOn": []
        }
      ],
      "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,
      "inOpportunityZone": null,
      "inFemaFloodZone": null,
      "propertyType": "residential",
      "propertyTypeLabel": "Residential",
      "landUses": [
        {
          "type": "residential",
          "typeLabel": "Residential",
          "subtype": "multifamily",
          "subtypeLabel": "Multifamily",
          "assetClass": null,
          "assetClassLabel": null,
          "matchedOn": []
        }
      ],
      "status": "continued",
      "statusLabel": "Continued"
    }
  ],
  "meta": {
    "schemaVersion": "2026-09-16",
    "representation": "compact",
    "limit": 2,
    "creditsUsed": 2,
    "creditsRemaining": 284,
    "delivery": {
      "mode": "all",
      "notPreviouslyExported": 1,
      "previouslyExported": 1,
      "updatedSinceExport": 1,
      "billed": 2,
      "notRebilled": 0,
      "ledgerApplied": true
    },
    "sync": {
      "cursor": "eyJ1cGRhdGVkQXQiOiIyMDI2LTA4LTAyVDE0OjA5OjIyWiIsImlkIjoxOTE3NzR9",
      "hasMore": true,
      "watermark": "2026-08-02T14:09:22+00:00",
      "highWater": "2026-08-03T00:00:00+00:00",
      "emitted": 2,
      "pageSize": 2,
      "candidatesScanned": 2
    }
  }
}

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.

Two records here tell the whole story. The first has never been delivered to you — alreadyExported: false, billed: true. The second you received on 19 July and it has changed since — alreadyExported: true, updatedSinceExport: true, billed: true. A third record that you held and which had not changed would come back with billed: false and cost nothing.

meta.delivery totals it for the page: how many were new to you, how many you had seen, how many changed, how many were billed, and how many were delivered without a charge.

Credit costFree — 0 creditsCounty, State, and National: free. Standalone API Only and the free trial: 1 credit per new or changed record; unchanged owned records bill 0.

How it scales

RunRecords returnedBillableCredits
First full walk of your market2,0002,0002,000
Next morning2,000 matched, 34 changed or new3434
Morning after that, nothing moved2,000 matched, 0 changed00

This is the shape of a steady-state integration: an expensive first pull and a near-free daily delta. Budget for the first walk, not for the cadence.

What can go wrong

  • 400 invalid_cursor: the cursor was created for a different filter set or a different entitlement scope. Repeat the request without the cursor; restarting is cheap because records you already hold are not re-billed.
  • sort, order, offset and page are refused on the sync feed. A caller-chosen ordering would break the losslessness guarantee while appearing to work, which is the worst way for a guarantee to fail. Use /projects/search when you want your own ordering.

Next

Ready to make a call?

A free Boardwalk trial includes API access, 50 record-export credits (search, CSV, MCP), and 5 Find Contact Info lookups. Counting, taxonomy, location lookups and the analytics plane cost nothing, so you can evaluate the data before you spend a credit.