Skip to main content

About

Programmatic access to the property database: search by address, parcel, or MLS id, fetch property details and attributes, run your saved property filters, count signal events, organize properties with tags and lists, and skip-trace owners. Shared filter-authoring operations also support CONTACT and DEAL filters. All operations go through the developer API gateway — one endpoint, called by operationId. If you haven’t set up a key yet, start with the Developer API Overview.
Property idsThe search operations (findProperties, findPropertiesByParcel, findPropertiesByMlsId) return the property id to use everywhere else — pass it as-is to getProperty, getRelatedProperties, tag/list operations, and skip tracing.

Operations

Lookup and search (READ scope)

Address/parcel/MLS searches are paginatedfindProperties, findPropertiesByParcel, and findPropertiesByMlsId return up to 50 matches per call (a larger limit is clamped) but take an offset, and return totalCount + hasMore — so you can page through the full result set: send offset: 0, then offset: 50, and so on until hasMore is false. See Result limits & truncation.

Signal event counts (READ scope)

An event is a property’s signal of one type on one publication day; one property can contribute several events. Standing conditions such as absentee ownership are not events. This differs from filterProperties.total, which counts distinct matching properties. Express the area in the PROPERTY filter DSL: use a county’s fips from searchCounties or a city’s id from searchCities. includeIncompleteRecords widens the same completeness gate as on filterProperties.

Saved filters (READ + WRITE scopes)

filterProperties checks the resolved criteria against your organization’s plan, for both saved filterId and inline filterTree requests. A field the plan excludes causes an operation error with code PLAN_ENTITLEMENT_REQUIRED; it does not return an empty match set. Saving a filter does not preserve access to a feature your plan no longer includes. File a filter with saveFilter.folderId or updateFilter.folderId; explicit null on update removes it from its folder. Reuse a folder only when its name, parent, and privacy match. Deal filters run over one separately supplied pipeline; see the Deals API. filterProperties.sort.direction is ASC or DESC. Supported fields are spicy_lead_score, estimated_value_dollars, estimatedRent, last_property_signal_date (or lastPropertySignalDate), closed_date (or closedDate), unit_count (or unitCount), latestListingStatusDate (or z_latest_listing_status_date), fsboListedDate, frboListedDate, fsboListingRemovedDate, frboListingRemovedDate, listingRemovedDate, listingRemovedRentDate, listingRemovedSaleDate, and auction_date (earliest upcoming auction, properties with none last). Unknown fields are silently ignored, leaving the default order. includeIncompleteRecords: true includes properties normally hidden because they lack both parcel identity and a signal. It widens results and cannot turn off the same option already enabled in a saved filter’s queryOptions. Use the same option when previewing and submitting a filter-based list action. Saved-filter groups can carry negated: true to invert the whole group, including its nested groups and conditions. It is a group-level option; omitting it leaves the group uninverted.
Read the tree before you edit part of itupdateFilter replaces root wholesale. Editing one condition without calling getFilter first means re-authoring the tree blind and silently dropping every condition you didn’t know was there. Read it, change the one condition you mean to change, and send the modified tree back.Both saveFilter and updateFilter validate field ids and value shapes strictly. Discover fields with listFilterFieldNames, fetch the selected fields’ exact union arms with listFilterFields(fieldIds: [...]), and re-read the saved tree with getFilter after updating.
Hidden and retired fieldshidden describes visibility in the app’s filter builder; it does not mean a field is unusable. retired marks fields withdrawn from new authoring while existing saved conditions keep working. Prefer their replacements. listFilterFieldNames leaves retired fields out; explicitly requesting their ids with listFilterFields still returns details for interpreting saved trees. For contact filters, dealFilters combines stage, assignee, and close-date criteria on the same deal. The retired dealPipelineAndStages, dealUserIds, and dealCloseDateRange conditions can each match a different deal when combined.
Relay filter warningsA successful save or update can return warnings. These are not errors: the filter was persisted, but its criteria may deserve attention — for example, selecting same-named counties from different states. Show every warning to the user and correct the tree if it reveals an unintended selection.
Cities and counties are identified by id, not by nameA cityFilters condition takes the id from searchCities as its value (with label set to "Name, ST", e.g. "Memphis, TN"), and a countyFilters condition takes the 5-digit fips from searchCounties. saveFilter and updateFilter reject a bare city or county name: 11,347 US city names occur in more than one state, and a county name compiles to a county_fips term that would match nothing. Resolve the name to an id first.

Tags and lists (READ + WRITE scopes)

Selecting properties for a list action

Both list actions require totalCount and accept one selection form:
  • Explicit ids: send propertyIds and their count as totalCount. Omit filter and selection-window fields. To exclude a property, leave its id out.
  • Filter: send either filterId or filterTree, plus either selectAll: true or selectCount: N. A filter without either window, or with both, is rejected. Optional excludeIds applies only to this form. A saved filter must be visible to the key owner; an inline tree is strictly validated, so unknown field ids reject the call.
For select-all, read filterProperties first and pass its unsubtracted total as totalCount. This is an execution cap: understating it stops the job early. Exclusions are handled by the worker; do not subtract them. For explicit ids or selectCount, the server derives the cap from the id count or N, but totalCount remains a required, non-negative input. selectCount takes the first N in the worker’s default traversal order; it does not use a preview’s sort. For a sorted top-N, pass the sorted page’s explicit ids. Keep includeIncompleteRecords consistent with the preview, and review the match count before submitting a filter selection that could affect thousands of properties.

Skip tracing (ADMIN scope)

Credit-spending operationsSkip-trace operations spend your organization’s credits, so they require the ADMIN scope and the key owner must currently be a team admin. For high-volume server-to-server skip tracing there is also the standalone Skip Trace API.
Properties are global, not org-ownedUnlike deals or contacts, a property isn’t owned by any one organization — it’s shared reference data. So property operations are not org-guarded on the property id: any valid property id (esId) is readable, and referencing one never returns 403 forbidden. Your scope (READ / WRITE / ADMIN) still gates what you can do. The tags and lists you organize properties with are yours, though — a tag or list id from another org returns 403 forbidden. Saved filters you create are tied to your organization by the key. See Authorization for the model.

Example

Run a saved filter and page through the matches:
Full variable schemas, response shapes, and worked examples for every operation are available from the discovery endpoint.