Skip to main content
GET
List historical sold listing cycles
Each row is one observed sold listing cycle. A property can have several rows, even with the same closing date. The cycle ID identifies the event. The property ID identifies the parcel. Earlier sold cycles remain searchable after a newer listing replaces the current MLS record.

Choose an area and period

Use a point, address, parcel ID, viewport, ZIP list, or city. Address rules match the sale listing route. Use sold_since and sold_until for inclusive closing-date bounds. Use sold_price_min and sold_price_max for positive closing-price bounds. Missing prices or dates cannot satisfy their respective bounds. Distance is the default order with a reference point. Otherwise newest closing dates come first. Use sold_price_asc or sold_price_desc for closing-price order. Null values come last. Market and cycle ID break ties.

Read the coverage first

summary.coverage names the observed ZIPs and their first and last listing observation weeks in the selected markets. summary.partial_coverage is always true. Published observations do not establish complete transaction or area coverage. An unsupported market, ZIP filter, or area returns 422 history_unavailable. A search that overlaps a covered ZIP can still extend beyond published history. Only covered observations contribute to its results. A measured empty result does not prove that no property sold. The observation window dates the available history. It does not constrain the closing dates that those observations report. The response uses current assessor facts. It does not reconstruct bedrooms, area, condition, or ownership at the sale date.

Read the method

Method 1 uses cycles whose recorded outcome is sold. It excludes a cycle when its observed asking price is positive and below 10000 US dollars at any point. It also excludes cycles with a rental flag in their matched historical listing events. Missing flags do not establish verified sale classification. A sold cycle does not prove a recorded closing deed. The API never uses the newest listing to replace an older cycle’s sale date or price. summary.n_events counts matching cycles. summary.n_properties counts distinct properties in their markets. summary.sold gives closing-price and selling-time statistics over every match before pagination. Each median needs five usable observations. Each metric has its own usable count. The square-foot metric accepts only houses and condos with positive living area and closing price. Historical agent contact fields are not returned.

Pages and credits

The page and summary use the same database snapshot. A cursor binds the location, filters, sort, property version, and history versions. Restart pagination after invalid_cursor or a source refresh. Charges use the existing property identity with no base charge. Multiple cycles for the same property do not create new billing identities. Repeated property reads follow the shared account ledger. The summary has no separate charge.

Use the clients

Authorizations

Authorization
string
header
required

API key from the developer console (starts with zpka_). Create one at https://developers.investorlift.com/get-a-key. The same key works on POST /mcp.

Query Parameters

lat
number

Point latitude (with lng). With radius_miles it is the search geometry. With bbox it is the reference point only.

Required range: -90 <= x <= 90
lng
number

Point longitude (with lat).

Required range: -180 <= x <= 180
bbox
string

Viewport as west,south,east,north (WGS84 degrees). West must be less than east, south less than north, and the diagonal at most 40 mi. It must intersect a loaded market's coverage bbox (422 outside_coverage otherwise). It can carry lat + lng (without radius_miles) as the reference point for distances and sort=distance.

radius_miles
number

Search radius in miles around the point or around the centre of the property_id parcel, 0.25 to 20 (default 2). Not allowed with bbox.

Required range: 0.25 <= x <= 20
address
string

Street address to resolve before the radius search. Needs one five-digit ZIP or a city. ZIP takes precedence over city.

Required string length: 1 - 200
unit
string

Unit of the address. Only with address. An explicit unit takes precedence over a unit in the street line.

Required string length: 1 - 16
property_id
string

Parcel geometry: search around the centre of that parcel, with radius_miles. Not allowed with lat, lng or bbox.

Pattern: ^prop_[0-9a-f]{32}$
zip
string[]

ZIP list for a place search. With address, use exactly one five-digit ZIP. ZIP takes precedence over city for an address.

Required array length: 1 - 50 elements
Pattern: ^\d{5}$
city
string

Postal city for a place search or address resolution. With address, ZIP takes precedence when both are present.

Required string length: 1 - 100
segment
enum<string>[]

Keep these assessor segments: SFR, CONDO_TH, or OTHER.

Minimum array length: 1

Parcel segment: SFR, CONDO_TH (condo or townhouse) or OTHER, a mixed bucket of manufactured, multi-family, land and commercial parcels.

Available options:
SFR,
CONDO_TH,
OTHER
beds_min
integer

Minimum assessor bedroom count, inclusive.

Required range: 0 <= x <= 9007199254740991
beds_max
integer

Maximum assessor bedroom count, inclusive.

Required range: 0 <= x <= 9007199254740991
baths_min
number

Minimum assessor bathroom count, inclusive. A half bathroom counts as 0.5.

Required range: 0 <= x <= 9007199254740991
baths_max
number

Maximum assessor bathroom count, inclusive. A half bathroom counts as 0.5.

Required range: 0 <= x <= 9007199254740991
sqft_min
integer

Minimum living area in square feet, inclusive.

Required range: 0 <= x <= 9007199254740991
sqft_max
integer

Maximum living area in square feet, inclusive.

Required range: 0 <= x <= 9007199254740991
year_built_min
integer

Earliest assessor year built, inclusive.

Required range: 1600 <= x <= 2100
year_built_max
integer

Latest assessor year built, inclusive.

Required range: 1600 <= x <= 2100
sold_since
string<date>

Inclusive earliest closing date. Cycles without a closing date do not match.

sold_until
string<date>

Inclusive latest closing date. Cycles without a closing date do not match.

sold_price_min
integer

Inclusive minimum positive closing price, in whole US dollars.

Required range: 0 <= x <= 9007199254740991
sold_price_max
integer

Inclusive maximum positive closing price, in whole US dollars.

Required range: 0 <= x <= 9007199254740991
sort
enum<string>

Order by distance, newest closing date, or closing price. Null values come last. Market and cycle ID break ties.

Available options:
distance,
sold_desc,
sold_price_asc,
sold_price_desc
limit
integer
default:100

Page size, 1-500 (default 100).

Required range: 1 <= x <= 500
cursor
string

Opaque cursor from page.next_cursor of the previous page. A change of query, sort, weights or data version invalidates it (400 invalid_cursor). Then restart from page 1.

Required string length: 1 - 4096

Response

Default Response

data
object[]
required

The rows of this page.

page
object
required

Pagination: the page size, the rows returned and the cursor for the next page. Paged lists carry no total. The summary block does.

meta
object
required

Response metadata: when the API produced it, which markets it covers, and how fresh they are.

summary
object
required