Filter reference
Every parameter the record-returning endpoints accept, with its aliases, values and combination rules.
Generated from the same registry the API validates requests against. Anything listed here is accepted; anything not listed returns 400.
How filters combine
- Values within one parameter are an OR.
states=UT,COmeans Utah or Colorado. - Different parameters are ANDed.
states=UT&assetClasses=Apartment%20Buildingmeans Utah and apartment buildings. propertyTypes,propertySubtypesandassetClassesare OR-joined with each other first, then ANDed with everything else. Selecting a type and an unrelated asset class gives you the union, not the intersection.- Naming a county or city replaces the state scope rather than intersecting with it — the states you also sent are not searched in full, and the response says so with a
geography_narrowed_to_smallest_scopewarning inmeta.warnings. Because numeric ids skip name resolution, a county or city id that is not inside the states you named still wins: readmeta.appliedFiltersbefore you page.
An unknown parameter is refused, not ignored
curl 'https://api.boardwalkai.com/api/v1/projects/search?states=UT&estimatedProjectValueMin=1000000' \
-H 'Authorization: Bearer bwk_live_YOUR_KEY'Response · HTTP 400
{
"error": {
"code": "invalid_filter",
"message": "1 filter problem. No credits were charged.",
"param": "estimatedProjectValueMin",
"details": {
"problems": [
{
"param": "estimatedProjectValueMin",
"code": "unknown_parameter",
"message": "Unknown parameter \"estimatedProjectValueMin\". Nothing was charged.",
"details": []
}
]
},
"docsUrl": "https://boardwalkai.com/docs/api/errors#invalid_filter",
"requestId": "req_01K1QF3M0000EXAMPLE0001"
}
}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.
Defaults that are applied for you
Two defaults change which records a bare query returns, and they are disclosed in meta.appliedDefaults so you can assert on them rather than remember them. The same list also echoes taxonomyMatchMode and sort order — those do not change membership:
| Default | Effect | Opt out |
|---|---|---|
dateRange=last_1_year | A request with no date filter searches the last 12 months of meetings — the same window the web product shows. Reported in meta.appliedDefaults and as a default_date_window_applied warning. | dateRange=all |
leadTypes=private | A request with no leadTypes returns private development leads only — the same view as the map. Public projects (public), small private jobs (private_minor) and small public jobs (public_minor) are returned only when you name them; private is always included, so the parameter can only widen. Reported in meta.appliedDefaults; meta.appliedFilters.leadTypes echoes the view that ran. A projectIds read still applies this view — a public or minor id you already hold is hidden unless you widen leadTypes, or you fetch it with GET /projects/{id}. | leadTypes=private,public,private_minor,public_minor |
includeGovernmentDecisions=false | Still accepted and echoed so existing sync cursors keep working. It does not change the served set: sending true does not add public or paperwork rows. governmentDecisionSubtypes / governmentDecisionAssetClasses still require this flag or they 400, and once it is sent they narrow the whole result — including private leads — rather than Govt. Decisions only. Widen the view with leadTypes. | Omit it. Widen with leadTypes. |
taxonomyMatchMode=primary_only | A request that sends no taxonomy match mode matches the primary land use only. Always echoed in meta.appliedDefaults. | taxonomyMatchMode=primary_or_secondary |
sort=meetingDate, order=desc | Newest meeting evidence first. Order only — not membership. | Pass your own sort and order. |
The receipt
Every filtered response carries meta.appliedFilters — what actually ran after normalisation and name resolution — plus meta.appliedDefaults and meta.resolvedFrom. If you ever need to prove the API searched what you meant, diff those against what you sent.
Every filter
| Parameter | Type | Also accepted as | Description | Accepted values |
|---|---|---|---|---|
states | string (list) | state, stateId, stateIds | States, as numeric ids, USPS abbreviations ("UT") or full names ("Utah"). A list is an OR: pass every state you want. | From /api/v1/locations/states (free) |
counties | string (list) | county, countyId, countyIds | Counties, as numeric ids or names (a trailing "County" is optional). A name is resolved against a single states value when one is given. | From /api/v1/locations/states/{stateId}/counties (free) |
cities | string (list) | city, cityId, cityIds | Cities, as numeric ids or names. A name is resolved against a single states/counties value when one is given; an ambiguous name is an error, never a silently wider search. | From /api/v1/locations/states/{stateId}/counties/{countyId}/cities (free) |
bbox | object | bounds | Rectangle {north, south, east, west}. Records are returned only when their coordinates fall inside the rectangle — the engine prefilters with a circle and the corners of that circle are then removed. | — |
circle | object | — | Radius search {lat, lng, radiusMeters}. radiusMeters is 100–500000. | — |
polygon | geojson_ring | — | GeoJSON linear ring [[lng, lat], …], 4–1000 vertices, first vertex equal to last. The engine prefilters with the ring's bounding circle and exact point-in-polygon runs afterwards. | — |
propertyTypes | string (list) | type, types, propertyType | Building Type (top level), e.g. "Residential". Case-insensitive. | From /api/v1/taxonomy (free) |
propertySubtypes | string (list) | subtype, subtypes, propertySubtype | Building Type (2nd level). Also accepts "Type - Subtype" compounds, which are split server-side. | From /api/v1/taxonomy (free) |
assetClasses | string (list) | assetClass, assetClasses[] | Building Type class (3rd level), e.g. "Apartment Building". | From /api/v1/taxonomy (free) |
excludePropertySubtypes | string (list) | excludeSubtype, excludeSubtypes | Building Types (2nd level) to exclude. Applied after the Building Type match, as AND-NOT. | From /api/v1/taxonomy (free) |
excludeAssetClasses | string (list) | excludeAssetClass | Building Type classes to exclude. | From /api/v1/taxonomy (free) |
taxonomyMatchMode | string | — | Whether a Building Type has to be the project's primary one to count as a match. Defaults to primary_or_secondary whenever you filter on any Building Type level, so a project matches when it has the type you asked for — whether that is its headline use or one component of a larger development. The same rule applies at all three levels (propertyTypes, subtypes, assetClasses). Every delivered record names which of its types matched, and at which level, in landUses[].matchedOn. Send primary_only to count a project only when the type you searched for is its primary one — that returns fewer records and bills for fewer. | primary_only, primary_or_secondary, any |
status | string (list) | statuses, statusSelection | Entitlement Status. Accepts the machine token or the human label ("approved" or "Approved"). "unknown" selects records with no decision recorded. | pending, approved, denied, recommended_for_approval, recommended_for_denial, continued, referred, withdrawn, unknown |
decisionBodies | string (list) | decisionBody | The body that heard the request, normalised to its short name ("Salt Lake City Council" → "City Council"). Matching is exact against that short name, never a substring. | Planning & Development Services, Planning and Development Services, Community Development Department, Community Development Division, Development Services Department, Municipal Planning Authority, Historic Preservation, Redevelopment Agency, Reinvestment Agency, Building Commission, Building Authority, Planning Department, Planning Division, Planning Commission, Planning Director, Local Planning Body, Parks & Recreation, Board of Adjustment, Board of Appeals, Township Council, Development Services, County Council, City Council, City Staff, Town Council, Council, Commission, Mayor, Staff, other_bodies, unknown_status |
statusCombos | string (list) | statusCombo | "<body>|<status>" pairs, e.g. "City Council|approved". This is what the retired CC…/PC… buckets decompose into, and it is strictly more expressive. | — |
requestTypes | string (list) | requestType, applicationTypes, askType, askTypes | Application Type — what the applicant asked the jurisdiction for, e.g. "rezone". | conditional_use_permit, rezone, annexation, preliminary_plat, site_plan_approval, general_plan_amendment, development_agreement, subdivision_plat, variance, planned_unit_development, design_review |
decisionTypes | string (list) | decisionType | The kind of action recorded on the project. | — |
constructionTypes | string (list) | constructionType | Construction Type — what kind of construction the filing describes. | new_building, renovation, site_work, infrastructure, demolition_only |
projectSizes | string (list) | projectSize, constructionMagnitudes, constructionMagnitude | How large the construction is: large, medium or small — the same Project Size vocabulary the product uses. | large, medium, small |
constructionLeadsOnly | boolean | constructionLeadOnly | true keeps only records the pipeline marked as real construction leads. | — |
hasConstructionDetails | boolean | hasConstructionIntel | Whether construction details were extracted for this record. | — |
includeGovernmentDecisions | boolean | includeCivic, showAllRecords | Show Non-Real Estate Govt. Decisions. Defaults to false, matching the map — which reduces what a naive query bills for. Deprecated in favour of leadTypes, which is how the served set is widened now: it is still accepted and echoed, but it has no effect once lead-type serving is live — a Govt. Decision that is a real opportunity is a public lead and comes back when leadTypes names public, and one that is paperwork is not served at all. It will be retired with notice in the changelog. | — |
governmentDecisionSubtypes | string (list) | civicSubtypes | Requires includeGovernmentDecisions=true or the request is a 400. Once that flag is sent, this filter narrows the whole result — including private leads — rather than Govt. Decisions only. includeGovernmentDecisions itself does not add rows; use leadTypes to widen. | — |
governmentDecisionAssetClasses | string (list) | civicAssetClasses | Requires includeGovernmentDecisions=true or the request is a 400. Once that flag is sent, this filter narrows the whole result — including private leads — rather than Govt. Decisions only. includeGovernmentDecisions itself does not add rows; use leadTypes to widen. | — |
leadTypes | string (list) | leadType | Which lead types to return. Defaults to private — private development leads, the same view as the map. Add public (roads, schools, utilities, public buildings), private_minor (small private jobs: single homes, tenant finishes, lot splits) or public_minor to widen the view; private is always included. | private, public, private_minor, public_minor |
inOpportunityZone | string | — | Whether the project site is inside a federal Opportunity Zone (2018 designation). | inside, outside |
inFemaFloodZone | string | inSfha | Whether the site is inside a FEMA Special Flood Hazard Area — the 1%-annual-chance regulatory flood zone. | inside, outside |
meetingDateFrom | date | dateFrom | Earliest meeting date. Accepts YYYY, YYYY-MM, YYYY-MM-DD or RFC3339. Inclusive: a "To" bound snaps to the END of the period named. | — |
meetingDateTo | date | dateTo | Latest meeting date. Accepts YYYY, YYYY-MM, YYYY-MM-DD or RFC3339. Inclusive: a "To" bound snaps to the END of the period named. | — |
lastUpdatedFrom | date | updatedFrom, updatedAtFrom, updatedSince | Earliest last-updated date. On GET /projects/sync this seeds the first cursor and is then carried inside it, so it does not need re-sending on later pages. Accepts YYYY, YYYY-MM, YYYY-MM-DD or RFC3339. Inclusive: a "To" bound snaps to the END of the period named. | — |
lastUpdatedTo | date | updatedTo, updatedAtTo | Latest last-updated date. Accepts YYYY, YYYY-MM, YYYY-MM-DD or RFC3339. Inclusive: a "To" bound snaps to the END of the period named. | — |
dateRange | string | — | A relative meeting-date window. Defaults to last_1_year, matching what the product shows. Pass dateRange=all to search the whole corpus. | last_3_months, last_6_months, last_1_year, since_jan_2025, all |
totalUnitCountMin | number · count | unitCountMin | Lower bound for residential units. Inclusive. 0 is a real bound, not "unset". | — |
totalUnitCountMax | number · count | unitCountMax | Upper bound for residential units. Inclusive. 0 is a real bound, not "unset". | — |
acreageMin | number · acres | — | Lower bound for acres. “Projects over 2 acres” → acreageMin=2. Inclusive. 0 is a real bound, not "unset". | — |
acreageMax | number · acres | — | Upper bound for acres. “Projects over 2 acres” → acreageMin=2. Inclusive. 0 is a real bound, not "unset". | — |
lotSizeSqftMin | number · sqft | lotSizeMin | Lower bound in square feet for the same site area as acreage. Prefer acreageMin / acreageMax when you mean acres. | — |
lotSizeSqftMax | number · sqft | lotSizeMax | Upper bound in square feet for the same site area as acreage. Prefer acreageMin / acreageMax when you mean acres. | — |
squareFootageMin | number · sqft | — | Lower bound for commercial square footage. Inclusive. 0 is a real bound, not "unset". | — |
squareFootageMax | number · sqft | — | Upper bound for commercial square footage. Inclusive. 0 is a real bound, not "unset". | — |
parkingSpacesMin | number · count | — | Lower bound for parkingSpaces, in count. Inclusive. 0 is a real bound, not "unset". | — |
parkingSpacesMax | number · count | — | Upper bound for parkingSpaces, in count. Inclusive. 0 is a real bound, not "unset". | — |
buildingStoriesMin | number · count | storiesMin | Lower bound for buildingStories, in count. Inclusive. 0 is a real bound, not "unset". | — |
buildingStoriesMax | number · count | storiesMax | Upper bound for buildingStories, in count. Inclusive. 0 is a real bound, not "unset". | — |
buildingHeightFeetMin | number · feet | buildingHeightFtMin | Lower bound for buildingHeightFeet, in feet. Inclusive. 0 is a real bound, not "unset". | — |
buildingHeightFeetMax | number · feet | buildingHeightFtMax | Upper bound for buildingHeightFeet, in feet. Inclusive. 0 is a real bound, not "unset". | — |
bedroomCountMin | number · count | — | Lower bound for bedroomCount, in count. Inclusive. 0 is a real bound, not "unset". | — |
bedroomCountMax | number · count | — | Upper bound for bedroomCount, in count. Inclusive. 0 is a real bound, not "unset". | — |
floorCountMin | number · count | — | Lower bound for floorCount, in count. Inclusive. 0 is a real bound, not "unset". | — |
floorCountMax | number · count | — | Upper bound for floorCount, in count. Inclusive. 0 is a real bound, not "unset". | — |
q | string | search, query | Keyword search. Several words are matched as an exact phrase; pipe-separated groups ("mixed use|apartments") are alternatives. | — |
projectName | string | name | Project name search. Matches the project's name and display name only, as an exact phrase. | — |
developerName | string | developer, company | Developer or company name search over the parties named on the filing (developer, applicant, builder, owner, contractor, architect), as an exact phrase. Pulte and Pulte Homes are different searches; a prefix such as lenn matches nothing. | — |
requiresZoningChange | boolean | isRezone, rezoneOnly | Requires Zoning Change — keeps only records whose request changes the site's zoning (the record's isRezone field). Omit it, rather than sending false, to include everything. | — |
projectIds | integer (list) | ids | Exact record ids to fetch back — the read-back filter for records you already purchased (re-reads of unchanged owned records cost 0 credits). Positive integers, at most 100 per request. No default date window applies to an id selection (send dateRange or meetingDate bounds to window one deliberately). On GET /projects/search and /projects/sync it combines (AND) with every other filter; on the free GET /projects/count it must be the only filter — the count prices an id set as-is. An unknown id, or one outside your other filters or licensed geography, simply does not match. | — |
representation | string | — | Payload depth: compact, standard or full. All cost the same. | — |
include | string | — | Optional work to do before delivering: contacts. | — |
contactOptions | string | — | Enrichment options: minConfidence, maxProjects, cachedOnly, companyOnly. | — |
deliveryMode | string | — | all (default) returns every matching record with its delivery state disclosed; new returns only records never delivered to your account — the net-new-leads mode. Withheld records are counted in meta.delivery.excludedPreviouslyDelivered and are never billed. | — |
cursor | string | — | Opaque sync watermark from meta.sync.cursor on GET /projects/sync. Omit it to start a fresh sync — a restart is free for every record you already hold that has not changed. | — |
page | string | — | Page number, 1-based. | — |
limit | string | — | Records per page. | — |
offset | string | — | Record offset. Retained while page-based pagination lands. | — |
format | string | — | json (default) or csv. | — |
maxCredits | string | — | On format=csv only: the spend ceiling acknowledged for this export. The file still includes already-owned unchanged rows at 0 credits. If the new/changed rows would cost more than this, the request is refused and nothing is queued. | — |
excludeProjectIds | string | — | Subtract these project ids from search and count (at most 100). Applied after the candidate pipeline so the quote matches what would ship. | — |
excludeSaved | string | — | When 1, subtract every project on a saved list this caller can see, including Saved. | — |
excludeAlertId | string | — | Subtract every project any delivery of this alert (alr_…) has ever materialised. | — |
sort | string | — | Ordering field. The product's own sort tokens are accepted as aliases. Direction-bearing aliases such as units_lowest encode their order; a conflicting order parameter is rejected. | meetingDate, lastUpdated, dataRichness, totalUnitCount, acreage |
order | string | — | asc or desc. Omit this for a direction-bearing sort alias, or send the direction its suffix implies; a conflict is rejected. | asc, desc |
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.