Sales
Search sales with filters
Search and list individual real-estate sale transactions and active listings with filters — one row per sale/listing. Filter by location (state, county, city, zip), sale price, sale or listing date, property characteristics (beds, baths, square footage, property type), and listing status, with sorting and cursor pagination. This is the discrete per-transaction sales-record search: use it to find specific sales or build a filtered list of sold/active listings. If you only need how many sales match and not the records themselves, send the same request body to countSales.
Authorization
Body application/json
advancedFiltersone ofShow child attributesHide child attributes
Option 1objectShow child attributesHide child attributes
childrenone of[]requiredArray of filter expressions (AND)
Same shape as its parent.
typeenumrequiredandOption 2objectShow child attributesHide child attributes
childrenone of[]requiredArray of filter expressions (OR)
Same shape as its parent.
typeenumrequiredorOption 3objectShow child attributesHide child attributes
childone ofrequiredSame shape as its parent.
typeenumrequirednotOption 4objectShow child attributesHide child attributes
fieldstringrequiredopenumrequiredComparison operator. exists means the field has a REAL value: on fields whose source records an unknown as an in-domain value (e.g. beds, squareFeet, lotSquareFeet, where an unrecorded measurement is stored as 0), those docs count as NOT existing. neq keeps docs with no value — it removes only what is known to equal the value, matching the reading of an exclusion.
eqneqgtgteltltebetweeninmatchgeoDistanceexiststypeenumrequiredfiltervaluenullComparison value
filtersone ofShow child attributesHide child attributes
Option 1objectShow child attributesHide child attributes
childrenone of[]requiredArray of filter expressions (AND)
Same shape as its parent.
typeenumrequiredandOption 2objectShow child attributesHide child attributes
childrenone of[]requiredArray of filter expressions (OR)
Same shape as its parent.
typeenumrequiredorOption 3objectShow child attributesHide child attributes
childone ofrequiredSame shape as its parent.
typeenumrequirednotOption 4objectShow child attributesHide child attributes
fieldstringrequiredopenumrequiredComparison operator. exists means the field has a REAL value: on fields whose source records an unknown as an in-domain value (e.g. beds, squareFeet, lotSquareFeet, where an unrecorded measurement is stored as 0), those docs count as NOT existing. neq keeps docs with no value — it removes only what is known to equal the value, matching the reading of an exclusion.
eqneqgtgteltltebetweeninmatchgeoDistanceexiststypeenumrequiredfiltervaluenullComparison value
flatFiltersobjectShow child attributesHide child attributes
bathsone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberbedsone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumbercatsAllowedbooleanLease listings. true: a cats-OK token. false: No, or dogs-only.
cityone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredcountyone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequireddogsAllowedbooleanLease listings. true: a dogs-OK token. false: No, or cats-only.
elementarySchoolone of | nullElementary school name as listed, one or an array (any-of). Matched case-insensitively with the generic words (School, Elementary, Middle, High) removed, so Lago Vista Elementary School and Lago Vista Elementary select the same listings. All remaining words must appear in the stored name. The assigned school is as named on the listing record, not a boundary lookup. List the available values for an area with POST /v1/sales/analytics/chart and slice: "elementarySchool".
Show child attributesHide child attributes
Option 1stringOption 2string[]fipsone of | null5-digit county FIPS code — the exact-code escape hatch for county (which also accepts a county name).
Show child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredfireplacebooleantrue: the listing has a fireplace. false: it says it does not. Rows with no answer match neither value.
garageSpacesone of | nullGarage spaces (e.g. {gte: 2}). Rows with no garage count are excluded unless includeNulls: true.
Show child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumbergeoBoundsobject | nullMap viewport {north, south, east, west} in degrees: only listings inside the box. west greater than east crosses the antimeridian. Unlike geoPoint (a radius) this is the shape a map reports. Applies to list, count and analytics alike.
Show child attributesHide child attributes
eastnumberrequirednorthnumberrequiredsouthnumberrequiredwestnumberrequiredgeoPointobject | nullRadius search — { lat, lon, radius } (e.g. radius "15mi" or "24km") — around any office on the agent's record; with locationSource office the CURRENT office, production their transactions.
Show child attributesHide child attributes
latnumberrequiredlonnumberrequiredradiusstringrequiredhasHoabooleantrue: the listing says it has an association, or carries a positive HOA fee. false: positive evidence of none (association flag N, or an explicit $0 fee) and no contradicting signal. A row with neither signal matches neither value.
highSchoolone of | nullHigh school name as listed, one or an array (any-of). Matched case-insensitively with the generic words (School, Elementary, Middle, High) removed, so Lago Vista Elementary School and Lago Vista Elementary select the same listings. All remaining words must appear in the stored name. The assigned school is as named on the listing record, not a boundary lookup. List the available values for an area with POST /v1/sales/analytics/chart and slice: "highSchool".
Show child attributesHide child attributes
Option 1stringOption 2string[]hoaFeeobject | nullMonthly-equivalent HOA fee in dollars: a quarterly fee is divided by 3, an annual fee by 12, and so on, so {lte: 300} means "at most $300 a month" whatever the listing's payment frequency. Only rows with a recognized recurring frequency (monthly, quarterly, semi-annual, annual, semi-monthly, weekly) are comparable; one-time, unknown and missing frequencies are excluded. Rows with no fee are excluded unless includeNulls: true (use that to also keep homes with no HOA fee on record, or hasHoa: false). Reads the primary association only.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep rows where the field is missing (a range drops them by default). Requires a bound.
ltnumberltenumberkeywordstring | nullWords that must ALL appear in the listing description (public remarks), in any order, case-insensitive. Plain text: operators and punctuation (* ? " ( ) AND OR - :) are not interpreted. At most 200 characters and 12 words; empty or punctuation-only is a 400. Stemmed (granite matches granites), not fuzzy. Listing text is -supplied; see the display rules that apply to it.
listPriceone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberlistingAgentone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredlotSizeSqftone of | nullLot size in square feet (1 acre = 43,560). Rows with no lot size are excluded unless includeNulls: true.
Show child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumbermiddleSchoolone of | nullMiddle school name as listed, one or an array (any-of). Matched case-insensitively with the generic words (School, Elementary, Middle, High) removed, so Lago Vista Elementary School and Lago Vista Elementary select the same listings. All remaining words must appear in the stored name. The assigned school is as named on the listing record, not a boundary lookup. List the available values for an area with POST /v1/sales/analytics/chart and slice: "middleSchool".
Show child attributesHide child attributes
Option 1stringOption 2string[]mlsStatusone of | nullShow child attributesHide child attributes
Option 1enumSLDACTPNDCancelledWDNEXPCNTOFFUNKRNTDRNTLSERNT-SLDRNT-ACTRNT-PNDRNT-WDNRNT-EXPRNT-LSERNT-RNTDOption 2enum[]Match any status
SLDACTPNDCancelledWDNEXPCNTOFFUNKRNTDRNTLSERNT-SLDRNT-ACTRNT-PNDRNT-WDNRNT-EXPRNT-LSERNT-RNTDOption 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredmodeenumandornewConstructionbooleantrue: the listing is flagged new construction, or its condition says new / under construction / to be built / pre-construction. false: flagged not-new and no such condition. A row with neither signal matches neither value.
petsAllowedbooleanLease listings (combine with propertyType: "Residential Lease"). true: cats OK, dogs OK or a plain Yes. false: No, with nothing permitting. Negotiable and detail-only values (size limit, deposit) with no OK token match neither value.
poolPrivatebooleantrue: the listing has a private pool. false: it says it does not. Community pools are not distinguished (feeds record them inconsistently). Rows with no answer match neither value.
priceReducedbooleantrue: the current list price is below the ORIGINAL list price. false: at or above it. Rows missing either price match neither value. (Not based on previousListPrice, which is unreliable.)
priceReductionPercentobject | nullHow far the current list price is below the ORIGINAL list price, in percent of the original: {gte: 5} = cut by at least 5%. Negative means the price was raised. Rows missing either price are excluded unless includeNulls: true. Pair with priceReduced: true to exclude unchanged listings from a lte range.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep rows where the field is missing (a range drops them by default). Requires a bound.
ltnumberltenumberpropertyIdone of | nullParcel id — every sale record of one property (the mmPropertyId on a loan or property record). Loans' propertyId selects the same parcel.
Show child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredpropertyTypeone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredsaleDateone of | nullShow child attributesHide child attributes
Option 1stringExact date, or a whole period: YYYY-MM-DD (that day), YYYY-MM (the whole month — "2025-06" = 2025-06-01 through 2025-06-30) or YYYY (the whole year). YYYYMMDD, MM/DD/YYYY, an ISO-8601 datetime and epoch milliseconds are also accepted. An unparseable value is a 400.
Option 2objectDate range. Excludes null/missing-field docs by default; add includeNulls: true to keep them. Bounds accept YYYY, YYYY-MM, YYYY-MM-DD, YYYYMMDD, MM/DD/YYYY, a full ISO datetime or epoch milliseconds; an unparseable bound is a 400. A partial bound denotes the whole period and expands to the edge that preserves the operator: gte/lt take the period START, gt/lte take the period END — so {gte: "2024"} means on/after 2024-01-01 and {lte: "2024"} means through 2024-12-31.
Show child attributesHide child attributes
gtstringgtestringincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires a bound.
ltstringltestringsalePriceone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberschoolDistrictone of | nullSchool district name, one or an array (any-of). Matched case-insensitively with the generic words removed, so Austin Independent School District, Austin ISD and AUSTIN select the same listings. Matches the district assigned at any level (elementary, middle or high). It is a name match, not a boundary lookup: Austin would also match a district named Austin Achieve, so pair it with a location filter. List the available values for an area with POST /v1/sales/analytics/chart and slice: "schoolDistrict".
Show child attributesHide child attributes
Option 1stringOption 2string[]soldAgentone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredsoldPriceone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumbersqftone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberstateone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredstoriesone of | nullNumber of stories: 3, [1, 2] or {lte: 1} for single level. Where the listing has no stories value the building's story count is used instead, which for a condo is the whole building. Rows with neither are excluded unless includeNulls: true.
Show child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberwaterfrontbooleantrue: waterfront property. false: it says it is not. Rows with no answer match neither value.
yearBuiltone of | nullShow child attributesHide child attributes
Option 1numberOption 2number[]Match any value
Option 3objectNumeric range. Excludes null/missing-field docs by default; add includeNulls: true to keep them.
Show child attributesHide child attributes
gtnumbergtenumberincludeNullsbooleanAlso keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.
ltnumberltenumberzipone of | nullShow child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredzipCodeone of | nullZIP code. Canonical key on sales (matches loans zipCode and the response DTO); zip is an alias kept for cross-entity parity.
Show child attributesHide child attributes
Option 1stringOption 2string[]Match any value
Option 3objectFuzzy text match
Show child attributesHide child attributes
matchstringrequiredpaginationobjectShow child attributesHide child attributes
cursorstringOpaque cursor from previous response for next page
sizeintegerPage size (1-100, default 25)
periodenumDate window for loans / sales / market endpoints. Accepts every Period value plus rolling windows: last30Days / last60Days / last90Days (today minus 30 / 60 / 90 days through today), previousMonth (the last complete calendar month) and currentMonth (the 1st of this month through today). All windows are resolved in UTC with inclusive calendar-date bounds. Rolling windows are only accepted by the loans, sales and market endpoints (list, count, breakdowns, analytics summary / time-series / chart); originators / companies / branches / agents / offices endpoints return 400 for them.
2017201820192020202120222023202420252026last3Monthslast6Monthslast12Monthslast14Monthslast16Monthslast18Monthslast24MonthsyearToDateallTimelast30Dayslast60Dayslast90DayspreviousMonthcurrentMonthsortobject[]Show child attributesHide child attributes
fieldenumrequiredcitystatezipCodecountysalePricesaleDatelistPricesoldPricelistingAgentsoldAgentmlsStatusbedsbathssqftyearBuiltpropertyTypeorderenumascdescResponses
200objectPaginated list of salesShow attributesHide attributes
cursorstringdataobject[]requiredShow child attributesHide child attributes
apnstring | nullbathsnumber | nullNumber of full bathrooms
bedsnumber | nullNumber of bedrooms
buyerNamestring | nullcitystring | nullcoListAgentIdstring | nullModelMatch agent ID for the co-listing agent, same rule
coListAgentNamestring | nullCo-listing agent's name as the recorded it
coordinatesobject | nullShow child attributesHide child attributes
latnumberrequiredlonnumberrequiredcumulativeDaysOnMarketnumber | nullCumulative days on market across relists, as the states it.
daysOnMarketnumber | nullfipsstring | nullidstringrequiredDocument ID
lastPriceChangeDatestring | nullDate of the most recent list-price change (YYYY-MM-DD). Roughly 60% filled on active listings.
listDatestring | nulllist date (YYYY-MM-DD)
listPricenumber | nullList price in dollars
listingAgentIdstring | nullModelMatch agent ID for the listing agent — the agent the keys resolve to (the agentSales / loans rule), else the sale's linked agent id
listingAgentNamestring | nullmediaobjectThe first listing photo found on the open web, how many were found, and where from. Present on a list or map row only while a non-expired found record exists for THIS listing, otherwise the key is absent. Same caveats as SaleMedia: third-party links, attribute to source.host, they can stop resolving.
Show child attributesHide child attributes
countintegerrequiredHow many photos exist for this listing (the full list is on GET /v1/sales/{id})
coverobjectrequiredsourceobjectrequiredmlsDaysOnMarketnumber | nullDays on market as the states it for this listing. Distinct from daysOnMarket, which is only filled on some sold rows.
mlsStatusenum | nullListing status code
SLDACTPNDCancelledWDNEXPCNTOFFUNKRNTDRNTLSERNT-SLDRNT-ACTRNT-PNDRNT-WDNRNT-EXPRNT-LSERNT-RNTDnullmmPropertyIdstring | nullProperty id of the parcel this listing was matched to — the same id the propertyId filter takes. May not resolve to a parcel in some counties: in Travis, Williamson (TX), Hillsborough (FL) and Wake (NC) the id on a listing is built from the account number and usually does NOT exist as a property record, while in e.g. Maricopa, Denver and Davidson it usually does. Do not treat it as a guaranteed join key to /v1/properties.
originalListDatestring | nullDate the property was first listed (YYYY-MM-DD), which can precede listDate when it was relisted.
originalListPricenumber | nullOriginal list price in dollars
pendingDatestring | nullDate the listing went pending (YYYY-MM-DD). Filled on about half of sold listings and few active ones.
previousListPricenumber | nullList price before the most recent change, in dollars. Can equal listPrice (a change recorded on the list date) and is not guaranteed to be consistent with lastPriceChangeDate — verify before presenting a price-history timeline. Roughly 60% filled on active listings, about a third on sold.
propertyTypestring | nullListing property type (e.g. Residential, Condo)
recordingDatestring | nullsalePricenumber | nullTransaction price in dollars
sellerNamestring | nullsoldAgentIdstring | nullModelMatch agent ID for the sold/buying agent, same rule
soldAgentNamestring | nullsoldDatestring | nullsold date (YYYY-MM-DD) — the close, which can differ from transactionDate (the recorded deed)
soldPricenumber | nullSold price in dollars
sqftnumber | nullLiving area in square feet
statestring | nullstreetAddressstring | nulltransactionDatestring | nullyearBuiltnumber | nullYear the property was built
zipCodestring | nulllocationNormalizationsobject[]How each location filter value resolved. Present when a city/county/state/zip filter was supplied.
Show child attributesHide child attributes
candidatesstring[]Location ids matching an ambiguous name, ranked. Use instantSearch or suggestLocations to pick one.
confidenceenumrequired"exact" — matched a dictionary entry as written. "normalized" — resolved to a different spelling or merged several candidates. "fallback" — NOT resolved; the raw value was passed through, so a zero result means the name was not recognized rather than empty.
exactnormalizedfallbackdisplayNamestringrequiredfieldstringrequiredThe filter key this applies to
idstringResolved location id — pass this back for an exact filter
normalizedstringrequiredoriginalstringrequiredvariantsstring[]Spellings actually queried against the index
totalnumberrequired400objectValidation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: "dictionary"` result), then pass that id back as the filter value.401objectUnauthorized403objectForbidden (authenticated, but missing required context — e.g. no active organization)404objectNot found413objectResponse payload too large — detail endpoint capped to fit Lambda response limits503objectSearch timed out or the cluster is overloaded — retry after `Retry-After` seconds.