Skip to main content

The free sandbox

What 100 trial credits buy, which endpoints cost nothing, and the two ways a trial key behaves differently.

Who this is for

You are evaluating. You want to know whether the data is any good before anyone signs anything.

What you get

A free Boardwalk trial includes API access with a bwk_test_ key and a balance of trial credits, metered exactly like a paid balance: 1 credit per record delivered. Trial credits do not reset monthly — they are a one-off evaluation budget.

Billable — 1 credit per record delivered

MethodPathCostNotes
GET/alerts/{alertId}/matches1 credit / recordRecords already delivered and billed by a scheduled run are re-readable here without a second charge; anything new to you bills once.
POST/alerts/{alertId}/run1 credit / recordA manual run is a real delivery: records new to you bill at the standard rate. Runs are capped per alert per day.
GET/documents/{id}1 credit / recordOne source document, one credit.
POST/projects/ai-search1 credit / recordThe same rate as a structured search. You pay for confirmed matches that are delivered, not for the candidates that were reviewed and rejected.
POST/projects/ai-search/jobs1 credit / recordCredits are reserved up front against the requested limit and settled down to the number of confirmed records actually delivered.
GET/projects/search1 credit / recordCharged for the records actually delivered on the page, after duplicate projects are collapsed and after records you already hold unchanged are excluded. Zero results cost nothing.
GET/projects/sync1 credit / recordOnly records that are new to you, or that changed since you last received them, are billable. A sync page that returns nothing but unchanged records is free.
GET/projects/{id}1 credit / recordOne record, one credit — the same rate as a record inside a search page.

Free — 0 credits

MethodPathCostNotes
GET/account/creditsFreeFree. Your balance, your plan and your rate limit.
GET/alertsFreeFree. Configuring alerts never costs credits; only delivered records do.
POST/alertsFreeFree.
GET/alerts/{alertId}FreeFree.
PATCH/alerts/{alertId}FreeFree.
DELETE/alerts/{alertId}FreeFree.
GET/alerts/{alertId}/deliveriesFreeFree. The delivery history and what each run charged.
GET/alerts/{alertId}/deliveries/{deliveryId}FreeFree.
POST/alerts/{alertId}/dismissals/{projectId}FreeFree. Dismissing a match stops it being re-offered.
DELETE/alerts/{alertId}/dismissals/{projectId}FreeFree.
POST, GET/alerts/{alertId}/previewFreeFree. Preview returns how many records a rule would deliver and what that would cost, not the records themselves.
POST/analytics/aggregateFreeFree. Returns counts and group keys, never a project id, name, address, contact or document.
GET/analytics/datasetsFreeFree. What the analytics plane can and cannot answer, self-described.
POST/analytics/rankingsFreeFree, and subject to the same small-group suppression floor as /aggregate.
GET/healthFreeFree and unauthenticated.
GET/locations/cities/{id}FreeFree.
GET/locations/counties/{id}FreeFree.
GET/locations/statesFreeFree. Resolve the ids you filter with.
GET/locations/states/{id}FreeFree.
GET/locations/states/{id}/countiesFreeFree.
GET/locations/states/{stateId}/counties/{countyId}/citiesFreeFree.
GET/projects/ai-search/jobs/{id}FreePolling is free. The records the job delivers were charged when the job settled, not when you read them.
GET/projects/countFreeFree, always, including when your balance is zero. This is the endpoint that tells you what a query would cost before you buy it.
GET/taxonomyFreeFree. The complete land use taxonomy tree.
GET/taxonomy/action-categoriesFreeFree.
GET/taxonomy/action-typesFreeFree.
GET/taxonomy/asset-classesFreeFree.
GET/taxonomy/project-typesFreeFree.
GET/taxonomy/subtypesFreeFree.

Evaluate without spending

The whole planning surface is free, on a trial key and a paid key alike. You can establish coverage, vocabulary and result sizes for your market before spending a single credit:

  • GET /locations/* — is your market covered, and what are its ids?
  • GET /taxonomy/* — what vocabulary do we use for the thing you care about?
  • GET /projects/count — how many records match your real query, and what would they cost?
  • POST /analytics/aggregate — what does the shape of the market look like, without buying any records at all?

Add one filter and the same query becomes affordable

bash
curl 'https://api.boardwalkai.com/api/v1/projects/count?states=UT&assetClasses=Apartment%20Building&meetingDateFrom=2026-05-01&totalUnitCountMin=50' \
  -H 'Authorization: Bearer bwk_live_YOUR_KEY'

Response · HTTP 200

json
{
  "data": {
    "matchCount": 250,
    "matchCountIsExact": true,
    "matchCountBasis": "enumerated",
    "countedAs": "distinct_projects",
    "scanCeiling": 10000,
    "billable": {
      "records": 250,
      "credits": 250,
      "creditRate": 1,
      "isUpperBound": true,
      "nonBillable": {
        "alreadyDeliveredUnchanged": 0,
        "ledgerApplied": true
      }
    },
    "affordability": {
      "affordable": true,
      "blockReason": null,
      "shortfallCredits": 0,
      "maxAffordableRecords": 500,
      "boundBy": "period_balance",
      "unlimited": false
    },
    "ordering": {
      "sort": "meetingDate",
      "order": "desc",
      "tiebreak": null,
      "meaning": "Most recent meeting evidence first — the date of the meeting the record was extracted from, not when Boardwalk ingested it and not when the project was created."
    },
    "truncation": {
      "policy": "refuse",
      "wouldTruncate": false,
      "deliverableRecords": null,
      "explanation": "This request fits inside the remaining balance, so every matching record is delivered."
    }
  },
  "meta": {
    "schemaVersion": "2026-08-02",
    "representation": "standard",
    "deliveryMode": "all",
    "credits": {
      "limit": 500,
      "used": 0,
      "remaining": 500,
      "charged": 0,
      "periodStart": "2026-08-01",
      "periodEnd": "2026-08-31",
      "isTeamPool": true
    },
    "appliedFilters": {
      "states": [
        44
      ],
      "assetClasses": [
        "Apartment Building"
      ],
      "meetingDateFrom": "2026-05-01T00:00:00+00:00",
      "totalUnitCountMin": 50
    },
    "appliedDefaults": [],
    "resolvedFrom": {
      "states": {
        "UT": 44
      }
    },
    "warnings": [
      {
        "code": "filter_evidence_unconfirmed",
        "message": "These filters currently match our full index. A returned record with a null value for the attribute you filtered on is a record we could not confirm.",
        "params": [
          "assetClasses",
          "totalUnitCountMin"
        ]
      }
    ]
  },
  "links": {
    "self": "https://api.boardwalkai.com/api/v1/projects/count?states=UT&assetClasses=Apartment%20Building&meetingDateFrom=2026-05-01&totalUnitCountMin=50",
    "search": "https://api.boardwalkai.com/api/v1/projects/search?states=UT&assetClasses=Apartment%20Building&meetingDateFrom=2026-05-01&totalUnitCountMin=50",
    "docs": "https://boardwalkai.com/docs/api/budgets/"
  }
}

The response shape on this page is the one the endpoint builds — the keys, their nesting and their types are asserted against the shipping code by a test. The numbers inside it are the scenario being walked through, not a measurement of the corpus.

That call cost nothing and told you the query matches 250 records. Now you know exactly what 100 trial credits will and will not cover.

The two differences you need to know about

The second difference is contact data. On a trial key, external parties' contact channels — email, phone, LinkedIn — are withheld, and the record says so rather than pretending the filing had none:

The same record on a free-trial key

bash
curl 'https://api.boardwalkai.com/api/v1/projects/search?states=UT&limit=1' \
  -H 'Authorization: Bearer bwk_live_YOUR_KEY'

Response · HTTP 200

json
{
  "data": [
    {
      "id": 184203,
      "recordType": "project",
      "projectName": "Alta Ridge Phase II",
      "projectHeadline": "Planning Commission approved 240 apartments with conditions",
      "boardwalkLink": "https://boardwalkai.com/map/#project=184203",
      "mergedFrom": [
        184203,
        184987
      ],
      "createdAt": "2026-05-04T00:00:00Z",
      "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",
      "postalCode": "84119",
      "latitude": 40.6916,
      "longitude": -112.0011,
      "locationPrecision": "address",
      "locationPrecisionLabel": "Address",
      "isApproximate": false,
      "parcelApn": [
        "15-27-301-004"
      ],
      "propertyType": "residential",
      "propertyTypeLabel": "Residential",
      "propertySubtype": "multifamily",
      "propertySubtypeLabel": "Multifamily",
      "assetClass": "Apartment Building",
      "assetClassLabel": "Apartment Building",
      "status": "approved_with_conditions",
      "statusLabel": "Approved with Conditions",
      "statusDetail": "The commission approved the preliminary plat subject to eight conditions.",
      "requestType": "final_plat",
      "requestTypeLabel": "Final Plat",
      "decisionBody": "Planning Commission",
      "caseNumbers": [
        "PLAT-2026-0142"
      ],
      "acreage": 9.8,
      "unitCount": [
        {
          "count": 240,
          "type": "apartment",
          "typeLabel": "Apartment"
        }
      ],
      "totalUnitCount": 240,
      "existingZoning": "A-1",
      "proposedZoning": "RM-16",
      "isRezone": true,
      "constructionType": "new_building",
      "constructionTypeLabel": "New Building",
      "ownerType": "private",
      "ownerTypeLabel": "Private",
      "constructionDescription": "A 240-unit garden-style apartment community on 9.8 acres.",
      "developerCompany": "Alta Ridge Development LLC",
      "developerCompanyRole": "developer",
      "developerCompanyRoleLabel": "Developer",
      "contacts": [
        {
          "name": "Rachel Okafor",
          "title": "Director of Development",
          "role": "developer",
          "roleLabel": "Developer",
          "partyClass": "external",
          "partyClassLabel": "External Party",
          "entityType": "person",
          "company": "Alta Ridge Development LLC",
          "email": null,
          "emailConfidence": null,
          "emailSource": null,
          "phone": null,
          "phoneConfidence": null,
          "phoneSource": null,
          "linkedinUrl": null,
          "linkedinConfidence": null,
          "linkedinSource": null,
          "contactProvenance": null,
          "enrichmentSource": null,
          "enrichedAt": null,
          "enrichmentStatus": "not_requested",
          "contactsWithheldReason": "free_tier"
        }
      ],
      "contactEnrichment": {
        "status": "not_requested",
        "statusLabel": "Not Requested",
        "attemptedAt": null,
        "contactsFound": 0,
        "source": "registry"
      },
      "publicOfficials": [
        {
          "name": "Dana Whitfield",
          "title": "Senior Planner",
          "role": "city_planner",
          "roleLabel": "City Planner",
          "partyClass": "government",
          "organization": "West Valley City"
        }
      ],
      "contactSummary": {
        "externalCount": 1,
        "governmentCount": 1,
        "unclassifiedCount": 0,
        "withEmail": 0,
        "withPhone": 0,
        "withLinkedin": 0,
        "enrichedCount": 0,
        "lowConfidenceWithheld": 0,
        "withheldCount": 1,
        "withheldReason": "free_tier"
      },
      "keyFacts": [
        {
          "fact": "240 apartment units across six buildings",
          "category": "unit_mix",
          "categoryLabel": "Unit Mix"
        }
      ],
      "evidence": "Commissioner Reyes moved to approve subject to conditions 1-8.",
      "voteSummary": {
        "yes": 2,
        "no": 1,
        "abstain": 0,
        "absent": 1,
        "total": 4,
        "isUnanimous": false,
        "meetingDate": "2026-06-17"
      }
    }
  ],
  "meta": {
    "schemaVersion": "2026-08-02",
    "representation": "standard",
    "total": 1,
    "limit": 1,
    "offset": 0,
    "creditsUsed": 1,
    "creditsRemaining": 99,
    "trialTruncation": null,
    "searchMethod": "redisearch",
    "appliedFilters": {
      "states": [
        44
      ]
    },
    "appliedDefaults": [
      "dateRange=last_1_year"
    ],
    "resolvedFrom": {
      "states": {
        "UT": 44
      }
    },
    "warnings": [
      {
        "code": "default_date_window_applied",
        "message": "No date filter was given, so the last 12 months of meetings were searched — the same window the product shows. Pass dateRange=all to search everything.",
        "params": [
          "meetingDateFrom"
        ]
      }
    ],
    "matchCount": 8842,
    "matchCountIsExact": true,
    "duplicatesCollapsed": 0,
    "collapseApplied": true,
    "delivery": {
      "mode": "all",
      "notPreviouslyExported": 1,
      "previouslyExported": 0,
      "updatedSinceExport": 0,
      "billed": 1,
      "notRebilled": 0,
      "ledgerApplied": 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.

Look at contactSummary.withheldCount and withheldReason, and at contactsWithheldReason on the party itself. The names, titles, roles and companies are all there — enough to judge whether the contact data is worth paying for, which is the point of an evaluation. Government staff contact details are never returned on any tier, trial or paid.

Next

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.