curl --request GET \
--url https://api.investorlift.com/v1/properties/{property_id}/comps \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.investorlift.com/v1/properties/{property_id}/comps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.investorlift.com/v1/properties/{property_id}/comps"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": {
"subject": {
"property_id": "<string>",
"market": "<string>",
"address_short": "<string>",
"city": "<string>",
"zip": "<string>",
"latitude": 0,
"longitude": 0,
"bedrooms": 0,
"bathrooms": 123,
"sqft": 0,
"year_built": 0,
"last_sale": {
"sold_on": "<string>",
"sold_price": 0
}
},
"comps": [
{
"property_id": "<string>",
"market": "<string>",
"address_short": "<string>",
"city": "<string>",
"zip": "<string>",
"distance_miles": 123,
"sold_on": "<string>",
"sold_price": 0,
"price_per_sqft": 123,
"bedrooms": 0,
"bathrooms": 123,
"sqft": 0,
"year_built": 0,
"source": "DEED",
"days_on_market": 0,
"list_price": 0,
"cash_sale_proxy": true,
"last_sale_lender": "<string>",
"deal": {
"id": "<string>",
"kind": "flip",
"investor_id": "<string>",
"gross_profit": 0,
"hold_days": 0
},
"similarity": 0.5
}
],
"summary": {
"n": 0,
"n_deed": 0,
"n_mls": 0,
"median_price": 123,
"median_price_per_sqft": 123,
"price_per_sqft_value": 123,
"min_price": 123,
"max_price": 123,
"radius_miles": 123,
"window_start": "<string>",
"window_end": "<string>",
"sources": [
"DEED"
],
"tolerances": {
"bedrooms": 0,
"sqft_pct": 0,
"year_built": 0
}
}
},
"meta": {
"generated_at": "<string>",
"coverage": [
{
"market": "<string>",
"state": "<string>",
"counties": [
{
"fips": "<string>",
"name": "<string>",
"data_end": "<string>"
}
],
"bbox": [
0,
0,
0,
0
],
"data_end": "<string>",
"build_run_id": 0,
"registry_run": 0,
"registry_version": "<string>",
"dataset_version": 0,
"loaded_at": "<string>",
"metro_buy_to_resale_ratio": 123,
"universe_kind": "zip",
"universe_zips": [
"<string>"
],
"point_tolerance_miles": 123,
"n_parcels": 0,
"listings_data_end": "<string>",
"agents_data_end": "<string>",
"wholesale_as_of": "<string>",
"str_as_of": "<string>",
"str": {
"jurisdictions": [
{
"name": "<string>",
"regime": "REQUIRED",
"coverage_reason": "LOADED_SERVED",
"served": true,
"snapshot_only": true,
"licence_start": "<string>",
"snapshot_date": "<string>",
"feed_stale": true,
"sources": [
{
"source": "<string>",
"snapshot_date": "<string>",
"stale": true
}
],
"n_licensed": 0,
"n_pending": 0,
"n_expired": 0,
"n_advertised": 0,
"share_unmatched": 123,
"share_assumed": 123
}
]
},
"auction_counted": true,
"parcel_as_of": "<string>",
"address_as_of": "<string>",
"parcel": {
"parcel_as_of": "<string>",
"n_parcels": 0,
"sale_mortgage_measured": true,
"financing": {
"as_of": "<string>",
"dated": true,
"dated_reason": "<string>",
"n_parcels": 0,
"n_with_open_lien": 0,
"n_free_and_clear": 0,
"n_avm": 0,
"n_involuntary": 0,
"n_lenders": 0
},
"permits": {
"as_of": "<string>",
"n_permits": 0,
"n_parcels": 0,
"n_unmatched": 0,
"jurisdictions": [
{
"jurisdiction": "<string>",
"n_permits": 0,
"last_issue_date": "<string>",
"windows_measured": true
}
]
},
"owner_profile": {
"as_of": "<string>",
"n_parcels": 0,
"n_multi": 0,
"n_portfolio_5": 0
},
"history": {
"first_week": "<string>",
"last_week": "<string>",
"zips": [
"<string>"
],
"n_parcels": 0,
"n_events": 0,
"n_weeks": 0,
"domains": {}
}
},
"lenders": {
"as_of": "<string>",
"recordings_through": "<string>",
"counties": [
"<string>"
],
"history_capture_share": 123,
"n_lender_ids": 0,
"purchase_measured": true,
"investor_lending_measured": true,
"flips_measured": true,
"borrowers_measured": true,
"takebacks_measured": true,
"counties_measured": true,
"dated": true,
"n_parcels_uncovered": 0
}
}
],
"terms": "<string>",
"weights": {},
"reference_point": {
"lat": 0,
"lng": 0
},
"geometry": {
"kind": "radius",
"lat": 0,
"lng": 0,
"radius_miles": 123,
"bbox": {
"[0]": 0,
"[1]": 0,
"[2]": 0,
"[3]": 0
},
"property_id": "<string>",
"zip": [
"<string>"
],
"city": "<string>"
},
"resolved_from": [
"<string>"
],
"dated": [
{
"block": "valuation",
"as_of": "<string>",
"reason": "<string>"
}
]
}
}Read a parcel's comps
One parcel’s comparable sales, most similar first, from deeds and the MLS, with each sale’s investor exit and an indicative price per square foot.
curl --request GET \
--url https://api.investorlift.com/v1/properties/{property_id}/comps \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.investorlift.com/v1/properties/{property_id}/comps', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.investorlift.com/v1/properties/{property_id}/comps"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": {
"subject": {
"property_id": "<string>",
"market": "<string>",
"address_short": "<string>",
"city": "<string>",
"zip": "<string>",
"latitude": 0,
"longitude": 0,
"bedrooms": 0,
"bathrooms": 123,
"sqft": 0,
"year_built": 0,
"last_sale": {
"sold_on": "<string>",
"sold_price": 0
}
},
"comps": [
{
"property_id": "<string>",
"market": "<string>",
"address_short": "<string>",
"city": "<string>",
"zip": "<string>",
"distance_miles": 123,
"sold_on": "<string>",
"sold_price": 0,
"price_per_sqft": 123,
"bedrooms": 0,
"bathrooms": 123,
"sqft": 0,
"year_built": 0,
"source": "DEED",
"days_on_market": 0,
"list_price": 0,
"cash_sale_proxy": true,
"last_sale_lender": "<string>",
"deal": {
"id": "<string>",
"kind": "flip",
"investor_id": "<string>",
"gross_profit": 0,
"hold_days": 0
},
"similarity": 0.5
}
],
"summary": {
"n": 0,
"n_deed": 0,
"n_mls": 0,
"median_price": 123,
"median_price_per_sqft": 123,
"price_per_sqft_value": 123,
"min_price": 123,
"max_price": 123,
"radius_miles": 123,
"window_start": "<string>",
"window_end": "<string>",
"sources": [
"DEED"
],
"tolerances": {
"bedrooms": 0,
"sqft_pct": 0,
"year_built": 0
}
}
},
"meta": {
"generated_at": "<string>",
"coverage": [
{
"market": "<string>",
"state": "<string>",
"counties": [
{
"fips": "<string>",
"name": "<string>",
"data_end": "<string>"
}
],
"bbox": [
0,
0,
0,
0
],
"data_end": "<string>",
"build_run_id": 0,
"registry_run": 0,
"registry_version": "<string>",
"dataset_version": 0,
"loaded_at": "<string>",
"metro_buy_to_resale_ratio": 123,
"universe_kind": "zip",
"universe_zips": [
"<string>"
],
"point_tolerance_miles": 123,
"n_parcels": 0,
"listings_data_end": "<string>",
"agents_data_end": "<string>",
"wholesale_as_of": "<string>",
"str_as_of": "<string>",
"str": {
"jurisdictions": [
{
"name": "<string>",
"regime": "REQUIRED",
"coverage_reason": "LOADED_SERVED",
"served": true,
"snapshot_only": true,
"licence_start": "<string>",
"snapshot_date": "<string>",
"feed_stale": true,
"sources": [
{
"source": "<string>",
"snapshot_date": "<string>",
"stale": true
}
],
"n_licensed": 0,
"n_pending": 0,
"n_expired": 0,
"n_advertised": 0,
"share_unmatched": 123,
"share_assumed": 123
}
]
},
"auction_counted": true,
"parcel_as_of": "<string>",
"address_as_of": "<string>",
"parcel": {
"parcel_as_of": "<string>",
"n_parcels": 0,
"sale_mortgage_measured": true,
"financing": {
"as_of": "<string>",
"dated": true,
"dated_reason": "<string>",
"n_parcels": 0,
"n_with_open_lien": 0,
"n_free_and_clear": 0,
"n_avm": 0,
"n_involuntary": 0,
"n_lenders": 0
},
"permits": {
"as_of": "<string>",
"n_permits": 0,
"n_parcels": 0,
"n_unmatched": 0,
"jurisdictions": [
{
"jurisdiction": "<string>",
"n_permits": 0,
"last_issue_date": "<string>",
"windows_measured": true
}
]
},
"owner_profile": {
"as_of": "<string>",
"n_parcels": 0,
"n_multi": 0,
"n_portfolio_5": 0
},
"history": {
"first_week": "<string>",
"last_week": "<string>",
"zips": [
"<string>"
],
"n_parcels": 0,
"n_events": 0,
"n_weeks": 0,
"domains": {}
}
},
"lenders": {
"as_of": "<string>",
"recordings_through": "<string>",
"counties": [
"<string>"
],
"history_capture_share": 123,
"n_lender_ids": 0,
"purchase_measured": true,
"investor_lending_measured": true,
"flips_measured": true,
"borrowers_measured": true,
"takebacks_measured": true,
"counties_measured": true,
"dated": true,
"n_parcels_uncovered": 0
}
}
],
"terms": "<string>",
"weights": {},
"reference_point": {
"lat": 0,
"lng": 0
},
"geometry": {
"kind": "radius",
"lat": 0,
"lng": 0,
"radius_miles": 123,
"bbox": {
"[0]": 0,
"[1]": 0,
"[2]": 0,
"[3]": 0
},
"property_id": "<string>",
"zip": [
"<string>"
],
"city": "<string>"
},
"resolved_from": [
"<string>"
],
"dated": [
{
"block": "valuation",
"as_of": "<string>",
"reason": "<string>"
}
]
}
}Use it when
- You have a parcel and want what houses like it sold for nearby. The parcel can come from
resolve, a deal’s
property.idor a search page. - You want the flip exits among the comps. A comp with a
dealblock is a sale whose purchase side the registry knows. Sogross_profitandhold_dayssay what the rehab returned. - Use POST /v1/properties/search instead when you want the raw parcels around a point with your own filters and no similarity. Use the deal scan when you want investor deals, not every sale.
How a comp is chosen
-
The subject. The parcel’s own facts set the tolerances:
bedrooms,sqftandyear_built. A fact the subject lacks cannot bound the comps. So the route does not apply that tolerance, andsummary.tolerancescarries null for it. The subject’s own last purchase appears ondata.subject.last_salefor reference and is never a comp. -
The candidates. Every parcel of the subject’s market inside
radius_miles, withinbeds_tolerancebedrooms,sqft_pctpercent of the living area andyear_toleranceyears of the subject. -
The sales. From the deed registry, the route takes the parcel’s arm’s-length last purchase (
source: DEED), the purchase the registry keeps for every parcel of every market. From the MLS, where the market has published listing tables (meta.coverage[].listings_data_end), it takes the parcel’s SOLD listing records (source: MLS), withdays_on_marketandlist_price. A rental listing is never a sale. Both must fall inside the window, the lastdays_backdays before the market’sdata_end, and carry a price. An unpriced deed, as in a non-disclosure state, is not a comp. - One sale per parcel. A parcel keeps its newest sale. When the deed and the MLS record the same sale, the MLS record wins if the deed recorded within 45 days of the close. So the comp carries the days on market.
-
The ranking.
similarityis one minus a weighted sum of five gaps, each over its own tolerance:- the distance over the radius (0.35)
- the size gap over the size tolerance (0.25)
- the bedroom gap over its tolerance (0.15)
- the age gap over its tolerance (0.10)
- the sale’s age over the window (0.15)
limit. A plan cap below it applies.
source picks the sources. mls in a market without listing tables answers
422 listings_unavailable. both serves only the deed side there, and
summary.sources says so.
Read the response
data.subject: the parcel, its coordinates and the facts the tolerances read.data.comps[]: the comp parcel and address,distance_miles,sold_on,sold_price,price_per_sqft, the building facts,source, the MLS fields,cash_sale_proxy,last_sale_lender,dealandsimilarity.cash_sale_proxyandlast_sale_lenderare null where the market has no parcel layer. They are also null where the layer’s last sale is a different sale, or where the market does not measure the proxy (meta.coverage[].parcel.sale_mortgage_measuredfalse).dealis the exit recorded within 45 days of the sale, the nearest one, or null.data.summary:n,n_deed,n_mls,median_price,median_price_per_sqft,price_per_sqft_value,min_price,max_price, the window, the sources read and the tolerances applied.price_per_sqft_valueis the median price per square foot times the subject’s living area, in whole dollars. Every figure is over the comps returned, so a smalllimitnarrows them.meta.geometryechoes the subject as theradiusthat ran, withproperty_idthe subject. The envelope describes it.
price_per_sqft_value is an indication, not a valuation. The route makes no time adjustment, no condition adjustment
and no weighting by similarity. A valuation product is a later decision.
Credits
A call costs 2 credits, plus 1 for each comp parcel new to the account. A parcel already held by a search page or another comps call costs nothing again. See plans and limits.Gotchas
- The window ends at the market’s
data_end, the last deed date, not today.summary.window_endsays which day. - A parcel with no coordinates in any loaded market answers
404 not_found, like the other parcel routes. - The MLS side needs the listing tables. The deed side needs nothing beyond the market itself, so the route answers in every loaded market.
- The largest request, five miles over three years in a dense area, runs for a second or two.
Authorizations
API key from the developer console (starts with zpka_). Create one at https://developers.investorlift.com/get-a-key.
Path Parameters
Parcel id, prop_<32 hex>, from /v1/properties/resolve or any deal's property.id. The prefix is part of the id (400 invalid_id otherwise).
1 - 64Query Parameters
Radius around the subject in miles, 0.1 to 5 (default 1).
0.1 <= x <= 5Sales in the last N days before the market's data_end, 30 to 1095 (default 180).
30 <= x <= 1095Bedrooms either side of the subject's, 0 to 5 (default 1). The API skips it when the subject's bedrooms are unknown.
0 <= x <= 5Percent either side of the subject's sqft, 0 to 50 (default 20). The API skips it when the sqft is unknown.
0 <= x <= 50Years either side of the subject's year_built, 0 to 50 (default 15). The API skips it when the year_built is unknown.
0 <= x <= 50With deed, the registry's arm's-length last purchases. With mls, SOLD listing records, and 422 listings_unavailable where the market has none. With both, the default, one sale per parcel, and the MLS record wins within 45 days of the deed.
deed, mls, both Comps to return, 1 to 50 (default 20), most similar first. A plan cap below this applies.
1 <= x <= 50Response
The comparable sales of one parcel.
The comparable sales of one parcel.
GET /v1/properties/{id}/comps: the subject, its comparable sales within the radius, the window and the tolerances, and the summary.
Show child attributes
Show child attributes
Response metadata: when the API produced it, which markets it covers, and how fresh they are.
Show child attributes
Show child attributes
Was this page helpful?