Runs
A search run against homes ("Search now"): its progress, its results with scores and reasons, and the order you curate. The old `/matches` paths still answer, and say they are old.
Search now
/api/v1/searches/{searchId}/runsRuns a search, as it stands, against its source, and answers the run. The run shows up in Searches and Clients, as it does in the app. Against Homes for sale an execution works in the background for a minute or two: the answer is 202 with status: "running", a Location (/api/v1/runs/{runId}) and a Retry-After. Against a data set the run is complete as soon as it is made: the answer is 201 with the results.
A search that names no place still runs. With no area, commute or pin, Homes for sale looks around the org's market, or Nashville, TN while none is set. A data set's search looks where that data set has the most homes.
Poll the same resource. GET /api/v1/runs/{runId} until status is complete, failed or canceled, honoring Retry-After between reads. When complete, the results are on that same payload.
Send an Idempotency-Key. With it, a retry answers the run the first one made (Idempotent-Replayed: true) and starts nothing new, whether the first was sent here or to the old /matches path; the same key for a different search is 409.
A run counts one against the org's monthly allowance and the person's own limit, and is recorded against the key that started it. It pins the search revision it ran, so editing the search later never changes it.
When it's ready. The body is optional. notify says who hears when the run finishes: you, the search's client (client, off unless sent), and up to five more emails or mobile numbers (also). The client and the people named get the public share link only when the Fair Housing review passed or warned. notify.callbackUrl asks for a signed callback when it ends; see Get told when a run finishes.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
Idempotency-Key | Header | string | Optional | A value of your own for this attempt. The same key with the same request replays the first answer (Idempotent-Replayed: true) and starts nothing new; the same key with a different request is 409. A key is remembered for as long as its run exists. |
Request body
Optional. notify names who hears when the run is ready, and notify.callbackUrl where a signed callback goes. A callback needs a key with a signing secret. The body is optional.
Fields (7)
| Field | Type | Required | Description |
|---|---|---|---|
notify | object | Optional | Who hears when the run is ready: you, the client, up to five more, and a callback URL. Left out: your profile decides for you, and no one else hears. |
notify.agent | object | Optional | Tell me: you, by text and by email. |
notify.agent.text | boolean | Optional | Text you when it is ready. Left out: your profile's setting on a Homes for sale match, off on a data set match. |
notify.agent.email | boolean | Optional | Email you when it is ready. Left out: as text. |
notify.client | boolean | Optional | Send the client the share link by email, and by text when they have a mobile number, once the Fair Housing review passes or warns. Off when left out. |
notify.also | string[] | Optional | Up to five more emails or mobile numbers, each sent the share link the same way.at most 5 items |
notify.callbackUrl | string | Optional | 1 to 2000 characters |
{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}Examples
curl -X POST "https://liviamatch.com/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/runs" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Idempotency-Key: okafor-east-nashville-1" \
-H "Content-Type: application/json" \
-d '{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}'Responses
A live execution was queued. Read the run until status is not running.
HeadersLocationRetry-AfterETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "running",
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:03:11.402Z",
"dataAsOf": null,
"summary": null,
"funnel": null,
"reasonCounts": {},
"credits": [],
"notes": [],
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
}
]
},
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"execution": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "queued",
"step": null,
"stepLabel": null,
"attempts": 0,
"progress": {
"done": 0,
"total": 9,
"percent": 0
},
"startedAt": null,
"finishedAt": null,
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
},
"review": null
},
"counts": null,
"results": [],
"removed": [],
"excluded": [],
"emptyReason": null,
"compliance": {
"kind": "not_reviewed",
"overall": null,
"items": [],
"reviewedAt": null,
"source": null
},
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"search": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"results": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results",
"shares": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (270)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live execution; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no results yet: keep polling. complete, failed and canceled are final. |
data.searchId | string (uuid) | |
data.searchVersion | integer | The revision of the search this run ran. |
data.clientId | string (uuid) | null | The search's client, or null for a search that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set run. |
data.execution | object | null | The live execution behind a Homes for sale run; null for a data set run. |
data.execution.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.execution.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.execution.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.execution.stepLabel | string | null | That play in words for a person. |
data.execution.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.execution.progress | object | |
data.execution.progress.done | integer | Plays finished. |
data.execution.progress.total | integer | Plays in a run. |
data.execution.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.execution.startedAt | string (date-time) | null | |
data.execution.finishedAt | string (date-time) | null | |
data.execution.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.execution.error.code | string | |
data.execution.error.digest | string | null | |
data.execution.review | object | null | What the engine's prose review did on this run, as whole-number counts by name: summaryFlagged, summaryRepaired, summaryDropped, summarySectionsRebuilt, proseFlagged, proseRewritten, takesStandIn, repairCalls, and any count a newer engine adds (its verify… counts). Counts only, never the prose. Null when the engine sent none; a run on the built-in engine never has one. |
data.execution.links | object | |
data.execution.links.self | string | |
data.execution.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set run. |
data.counts | object | null | Null until the run is complete. |
data.counts.results | integer | Homes in the results. |
data.counts.removed | integer | Homes the run itself chose that you took out of the results. |
data.counts.excluded | integer | Homes the run graded and left out. |
data.counts.considered | integer | Homes the run weighed. |
data.results | object[] | The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete. |
data.results[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.results[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.results[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.results[].address | string | null | |
data.results[].area | string | null | The city. |
data.results[].state | string | null | |
data.results[].postalCode | string | null | |
data.results[].neighbourhood | string | null | |
data.results[].price | number | null | |
data.results[].beds | number | null | |
data.results[].baths | number | null | |
data.results[].sqft | number | null | |
data.results[].propertyType | string | null | |
data.results[].yearBuilt | integer | null | |
data.results[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.results[].images[].url | string (uri) | |
data.results[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.results[].location | object | null | |
data.results[].location.lat | number | |
data.results[].location.lng | number | |
data.results[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.results[].listedBy.office | string | |
data.results[].listedBy.listingKey | string | |
data.results[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.results[].details.status | string | at least 1 characters |
data.results[].details.yearBuilt | integer | null | |
data.results[].details.lotSqft | number | null | at least 0 |
data.results[].details.garageSpaces | number | null | at least 0 |
data.results[].details.daysOnMarket | integer | null | at least 0 |
data.results[].details.remarks | string | |
data.results[].details.features | string[] | |
data.results[].details.latitude | number | null | -90 to 90 |
data.results[].details.longitude | number | null | -180 to 180 |
data.results[].details.source | string | at least 1 characters |
data.results[].details.sourceUrl | string (uri), optional | |
data.results[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.results[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.results[].scoreParts.math | number | 0 to 100 |
data.results[].scoreParts.text | number | null | 0 to 100 |
data.results[].scoreParts.photos | number | null | 0 to 100 |
data.results[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.results[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.results[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.results[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.results[].highlights | string[] | |
data.results[].concerns | string[] | |
data.results[].lookAndFeel | string | null | |
data.results[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.results[].commutes[].label | string | 1 to 120 characters |
data.results[].commutes[].minutes | integer | 0 to 240 |
data.results[].commutes[].estimated | boolean | |
data.results[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.results[].signals.school | number | null | |
data.results[].signals.safety | number | null | |
data.results[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.results[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.results[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.results[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.removed | object[] | Homes the run itself chose that you took out of the results, in the run's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.excluded | object[] | Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.excluded[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the run used. Empty only when everything was live. |
data.emptyReason | object | null | Why a complete run showed no home, and the change summary suggests; null when it showed homes or is still running. |
data.emptyReason.code | string | The gate or step that left no home: nothing_in_the_area, no_listings_fetched, no_photographs, bed_bath_minimums, property_kind, dealbreakers, must_haves, commute_ceilings, or at the shortlist over_budget, kind_unreported, no_home_fits. Read an unknown code as no home fitting. |
data.emptyReason.stage | string | null | The funnel stage it names, or shortlist. |
data.emptyReason.before | integer | null | How many homes reached that gate; null when not counted. |
data.emptyReason.after | integer | null | How many it kept: 0. |
data.compliance | object | object | The Fair Housing checklist, or kind: "not_reviewed" with no items when the review did not run (a run with no homes is never reviewed). It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.search | string | The search it ran. |
data.links.results | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the run's shares. |
data.links.pdf | string | The run as a PDF (needs search:read). |
A data set answered at once: the run is complete.
HeadersLocationETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"execution": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
},
"review": null
},
"counts": {
"results": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"results": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"limits": []
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget",
"limits": []
}
],
"emptyReason": null,
"compliance": {
"kind": "not_reviewed",
"overall": null,
"items": [],
"reviewedAt": null,
"source": null
},
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"search": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"results": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results",
"shares": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (270)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live execution; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no results yet: keep polling. complete, failed and canceled are final. |
data.searchId | string (uuid) | |
data.searchVersion | integer | The revision of the search this run ran. |
data.clientId | string (uuid) | null | The search's client, or null for a search that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set run. |
data.execution | object | null | The live execution behind a Homes for sale run; null for a data set run. |
data.execution.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.execution.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.execution.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.execution.stepLabel | string | null | That play in words for a person. |
data.execution.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.execution.progress | object | |
data.execution.progress.done | integer | Plays finished. |
data.execution.progress.total | integer | Plays in a run. |
data.execution.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.execution.startedAt | string (date-time) | null | |
data.execution.finishedAt | string (date-time) | null | |
data.execution.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.execution.error.code | string | |
data.execution.error.digest | string | null | |
data.execution.review | object | null | What the engine's prose review did on this run, as whole-number counts by name: summaryFlagged, summaryRepaired, summaryDropped, summarySectionsRebuilt, proseFlagged, proseRewritten, takesStandIn, repairCalls, and any count a newer engine adds (its verify… counts). Counts only, never the prose. Null when the engine sent none; a run on the built-in engine never has one. |
data.execution.links | object | |
data.execution.links.self | string | |
data.execution.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set run. |
data.counts | object | null | Null until the run is complete. |
data.counts.results | integer | Homes in the results. |
data.counts.removed | integer | Homes the run itself chose that you took out of the results. |
data.counts.excluded | integer | Homes the run graded and left out. |
data.counts.considered | integer | Homes the run weighed. |
data.results | object[] | The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete. |
data.results[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.results[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.results[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.results[].address | string | null | |
data.results[].area | string | null | The city. |
data.results[].state | string | null | |
data.results[].postalCode | string | null | |
data.results[].neighbourhood | string | null | |
data.results[].price | number | null | |
data.results[].beds | number | null | |
data.results[].baths | number | null | |
data.results[].sqft | number | null | |
data.results[].propertyType | string | null | |
data.results[].yearBuilt | integer | null | |
data.results[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.results[].images[].url | string (uri) | |
data.results[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.results[].location | object | null | |
data.results[].location.lat | number | |
data.results[].location.lng | number | |
data.results[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.results[].listedBy.office | string | |
data.results[].listedBy.listingKey | string | |
data.results[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.results[].details.status | string | at least 1 characters |
data.results[].details.yearBuilt | integer | null | |
data.results[].details.lotSqft | number | null | at least 0 |
data.results[].details.garageSpaces | number | null | at least 0 |
data.results[].details.daysOnMarket | integer | null | at least 0 |
data.results[].details.remarks | string | |
data.results[].details.features | string[] | |
data.results[].details.latitude | number | null | -90 to 90 |
data.results[].details.longitude | number | null | -180 to 180 |
data.results[].details.source | string | at least 1 characters |
data.results[].details.sourceUrl | string (uri), optional | |
data.results[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.results[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.results[].scoreParts.math | number | 0 to 100 |
data.results[].scoreParts.text | number | null | 0 to 100 |
data.results[].scoreParts.photos | number | null | 0 to 100 |
data.results[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.results[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.results[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.results[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.results[].highlights | string[] | |
data.results[].concerns | string[] | |
data.results[].lookAndFeel | string | null | |
data.results[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.results[].commutes[].label | string | 1 to 120 characters |
data.results[].commutes[].minutes | integer | 0 to 240 |
data.results[].commutes[].estimated | boolean | |
data.results[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.results[].signals.school | number | null | |
data.results[].signals.safety | number | null | |
data.results[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.results[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.results[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.results[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.removed | object[] | Homes the run itself chose that you took out of the results, in the run's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.excluded | object[] | Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.excluded[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the run used. Empty only when everything was live. |
data.emptyReason | object | null | Why a complete run showed no home, and the change summary suggests; null when it showed homes or is still running. |
data.emptyReason.code | string | The gate or step that left no home: nothing_in_the_area, no_listings_fetched, no_photographs, bed_bath_minimums, property_kind, dealbreakers, must_haves, commute_ceilings, or at the shortlist over_budget, kind_unreported, no_home_fits. Read an unknown code as no home fitting. |
data.emptyReason.stage | string | null | The funnel stage it names, or shortlist. |
data.emptyReason.before | integer | null | How many homes reached that gate; null when not counted. |
data.emptyReason.after | integer | null | How many it kept: 0. |
data.compliance | object | object | The Fair Housing checklist, or kind: "not_reviewed" with no items when the review did not run (a run with no homes is never reviewed). It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.search | string | The search it ran. |
data.links.results | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the run's shares. |
data.links.pdf | string | The run as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid | The body failed validation: an unknown key, more than five notify.also addresses, one that is neither an email nor a mobile number, or a callbackUrl a callback may not use; issues names each. |
| 400 | invalid-json | The body is not JSON. |
| 400 | invalid-idempotency-key | The Idempotency-Key is malformed. |
| 402 | out-of-credits | The org has no runs left this month. |
| 402 | person-limit-reached | The person the key acts as has used their own monthly runs. |
| 404 | not-found | No such search in your workspace. |
| 409 | idempotency-key-reused | The Idempotency-Key was used for a different search. |
| 413 | too-large | The body is over its limit. |
| 422 | search-unrunnable | The search cannot run against its source as it stands: a place Homes for sale cannot find, a commute or a rental against a data set, no source, or nothing a client asked for. issues says which. |
| 422 | callback-url-refused | notify.callbackUrl is plain http to localhost on a deployment that is not development. |
| 422 | callback-needs-key | notify.callbackUrl was named by a signed-in session rather than an API key. |
| 422 | no-signing-secret | notify.callbackUrl was named and the key has no signing secret. |
| 429 | rate-limited | The hourly cap on starting runs is spent (the answer has no RateLimit header). |
| 429 | too-many-active | 3 runs are already queued or running. |
| 503 | search-unavailable | An outside service the run needs is not configured here. |
| 503 | studio-incomplete | A prompt the engine runs is incomplete in Livia's AI settings; issues names the step. Nothing was started or spent. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 monthly-cap-reached500 internal
List a search's runs
/api/v1/searches/{searchId}/runsThe runs of one search, newest first, each as a card reads it: where it stands and how many results it has, never the homes. Read a run for those. Pages by cursor, 20 at a time and up to 50.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/runs" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of runs.
{
"data": [
{
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"homes": 2,
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15"
}
}
],
"links": {
"next": null
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | |
data[].kind | "dataset" | "market" | |
data[].status | "complete" | "failed" | "running" | "canceled" | |
data[].searchId | string (uuid) | |
data[].searchVersion | integer | |
data[].homes | integer | null | How many homes are in the results; null until the run is complete. |
data[].createdAt | string (date-time) | |
data[].updatedAt | string (date-time) | |
data[].links | object | |
data[].links.self | string | |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such search in your workspace. |
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
List runs
/api/v1/runsYour runs of every search, of both kinds, newest first, each as a card reads it. Pages by cursor, 20 at a time and up to 50: follow links.next until it is null. A headless run started with POST /api/v1/search is not one of these.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/runs" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of runs.
{
"data": [
{
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"homes": 2,
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15"
}
}
],
"links": {
"next": null
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | |
data[].kind | "dataset" | "market" | |
data[].status | "complete" | "failed" | "running" | "canceled" | |
data[].searchId | string (uuid) | |
data[].searchVersion | integer | |
data[].homes | integer | null | How many homes are in the results; null until the run is complete. |
data[].createdAt | string (date-time) | |
data[].updatedAt | string (date-time) | |
data[].links | object | |
data[].links.self | string | |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Read a run
/api/v1/runs/{runId}Status and results on one GET. One run: where it stands, and, once status is complete, its results, every home with its score, its parts and its reasons, in the order you curated, plus what it left out and why.
While it is running the answer has no results yet and carries Retry-After. An execution nobody is driving (a crash, a deploy) is picked up again by this read, so keep polling until status is complete, failed or canceled. To stop a Homes for sale run, POST to execution.links.cancel.
credits and every home's listedBy are attribution a provider's terms and MLS rules require wherever the homes are shown. notes lists every stand-in the run used. compliance is a Fair Housing checklist, or an object of kind: "not_reviewed" with no items, never a clearance. A run with no homes says why in emptyReason and summary. The ETag names the results, for PUT .../results.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
runId | Path | string (uuid) | Required | The run's id: data.id from the answer that started it. |
Examples
curl "https://liviamatch.com/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The run.
HeadersETagRetry-After
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"execution": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
},
"review": null
},
"counts": {
"results": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"results": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"limits": []
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget",
"limits": []
}
],
"emptyReason": null,
"compliance": {
"kind": "not_reviewed",
"overall": null,
"items": [],
"reviewedAt": null,
"source": null
},
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"search": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"results": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results",
"shares": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "running",
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:03:11.402Z",
"dataAsOf": null,
"summary": null,
"funnel": null,
"reasonCounts": {},
"credits": [],
"notes": [],
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
}
]
},
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"execution": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "running",
"step": "grade",
"stepLabel": "Reading each home's words and photos",
"attempts": 1,
"progress": {
"done": 6,
"total": 9,
"percent": 71
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": null,
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
},
"review": null
},
"counts": null,
"results": [],
"removed": [],
"excluded": [],
"emptyReason": null,
"compliance": {
"kind": "not_reviewed",
"overall": null,
"items": [],
"reviewedAt": null,
"source": null
},
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"search": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"results": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results",
"shares": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (270)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live execution; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no results yet: keep polling. complete, failed and canceled are final. |
data.searchId | string (uuid) | |
data.searchVersion | integer | The revision of the search this run ran. |
data.clientId | string (uuid) | null | The search's client, or null for a search that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set run. |
data.execution | object | null | The live execution behind a Homes for sale run; null for a data set run. |
data.execution.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.execution.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.execution.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.execution.stepLabel | string | null | That play in words for a person. |
data.execution.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.execution.progress | object | |
data.execution.progress.done | integer | Plays finished. |
data.execution.progress.total | integer | Plays in a run. |
data.execution.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.execution.startedAt | string (date-time) | null | |
data.execution.finishedAt | string (date-time) | null | |
data.execution.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.execution.error.code | string | |
data.execution.error.digest | string | null | |
data.execution.review | object | null | What the engine's prose review did on this run, as whole-number counts by name: summaryFlagged, summaryRepaired, summaryDropped, summarySectionsRebuilt, proseFlagged, proseRewritten, takesStandIn, repairCalls, and any count a newer engine adds (its verify… counts). Counts only, never the prose. Null when the engine sent none; a run on the built-in engine never has one. |
data.execution.links | object | |
data.execution.links.self | string | |
data.execution.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set run. |
data.counts | object | null | Null until the run is complete. |
data.counts.results | integer | Homes in the results. |
data.counts.removed | integer | Homes the run itself chose that you took out of the results. |
data.counts.excluded | integer | Homes the run graded and left out. |
data.counts.considered | integer | Homes the run weighed. |
data.results | object[] | The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete. |
data.results[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.results[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.results[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.results[].address | string | null | |
data.results[].area | string | null | The city. |
data.results[].state | string | null | |
data.results[].postalCode | string | null | |
data.results[].neighbourhood | string | null | |
data.results[].price | number | null | |
data.results[].beds | number | null | |
data.results[].baths | number | null | |
data.results[].sqft | number | null | |
data.results[].propertyType | string | null | |
data.results[].yearBuilt | integer | null | |
data.results[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.results[].images[].url | string (uri) | |
data.results[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.results[].location | object | null | |
data.results[].location.lat | number | |
data.results[].location.lng | number | |
data.results[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.results[].listedBy.office | string | |
data.results[].listedBy.listingKey | string | |
data.results[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.results[].details.status | string | at least 1 characters |
data.results[].details.yearBuilt | integer | null | |
data.results[].details.lotSqft | number | null | at least 0 |
data.results[].details.garageSpaces | number | null | at least 0 |
data.results[].details.daysOnMarket | integer | null | at least 0 |
data.results[].details.remarks | string | |
data.results[].details.features | string[] | |
data.results[].details.latitude | number | null | -90 to 90 |
data.results[].details.longitude | number | null | -180 to 180 |
data.results[].details.source | string | at least 1 characters |
data.results[].details.sourceUrl | string (uri), optional | |
data.results[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.results[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.results[].scoreParts.math | number | 0 to 100 |
data.results[].scoreParts.text | number | null | 0 to 100 |
data.results[].scoreParts.photos | number | null | 0 to 100 |
data.results[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.results[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.results[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.results[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.results[].highlights | string[] | |
data.results[].concerns | string[] | |
data.results[].lookAndFeel | string | null | |
data.results[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.results[].commutes[].label | string | 1 to 120 characters |
data.results[].commutes[].minutes | integer | 0 to 240 |
data.results[].commutes[].estimated | boolean | |
data.results[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.results[].signals.school | number | null | |
data.results[].signals.safety | number | null | |
data.results[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.results[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.results[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.results[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.removed | object[] | Homes the run itself chose that you took out of the results, in the run's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.excluded | object[] | Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.excluded[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the run used. Empty only when everything was live. |
data.emptyReason | object | null | Why a complete run showed no home, and the change summary suggests; null when it showed homes or is still running. |
data.emptyReason.code | string | The gate or step that left no home: nothing_in_the_area, no_listings_fetched, no_photographs, bed_bath_minimums, property_kind, dealbreakers, must_haves, commute_ceilings, or at the shortlist over_budget, kind_unreported, no_home_fits. Read an unknown code as no home fitting. |
data.emptyReason.stage | string | null | The funnel stage it names, or shortlist. |
data.emptyReason.before | integer | null | How many homes reached that gate; null when not counted. |
data.emptyReason.after | integer | null | How many it kept: 0. |
data.compliance | object | object | The Fair Housing checklist, or kind: "not_reviewed" with no items when the review did not run (a run with no homes is never reviewed). It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.search | string | The search it ran. |
data.links.results | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the run's shares. |
data.links.pdf | string | The run as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such run in your workspace. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Reorder or trim the results
/api/v1/runs/{runId}/resultsReplaces the results whole: the homes you name, in that order. That one call removes a home (leave it out), reorders (change the order) and adds one the run left out (name it). Every id must be a home from this run, each once, up to twenty; an empty list is allowed.
It writes only your list. The run's own result never changes, a home you take out moves to removed with its reasons kept, and a home you add from excluded carries outside, why the run left it out. A share you already sent keeps the homes it was sent with.
Without If-Match the last write wins. Send the ETag of the run you read as If-Match to refuse overwriting a list you have not seen: a list that changed since is 412 and nothing is written.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
runId | Path | string (uuid) | Required | The run's id: data.id from the answer that started it. |
If-Match | Header | string | Optional | The ETag of the run you read, such as "own" or "3f9a1c7d02ab". If the results have changed since, nothing is written and the answer is 412. |
Request body
The ordered ids of the homes to keep in the results.
Fields (1)
| Field | Type | Required | Description |
|---|---|---|---|
homes | string[] | Required | The ids of the homes you want in the results, in the order you want them, up to 20, each once. An id is a results[].id, removed[].id or excluded[].id from this run. An empty list is allowed.at most 20 items |
{
"homes": [
"NSH-2279012",
"NSH-2283104"
]
}Examples
curl -X PUT "https://liviamatch.com/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"homes": [
"NSH-2279012",
"NSH-2283104"
]
}'Responses
The run, with the results as you arranged them.
HeadersETag
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"searchId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"searchVersion": 1,
"execution": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
},
"review": null
},
"counts": {
"results": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"results": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"limits": []
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null,
"limits": []
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget",
"limits": []
}
],
"emptyReason": null,
"compliance": {
"kind": "not_reviewed",
"overall": null,
"items": [],
"reviewedAt": null,
"source": null
},
"links": {
"self": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"search": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"results": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/results",
"shares": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (270)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live execution; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no results yet: keep polling. complete, failed and canceled are final. |
data.searchId | string (uuid) | |
data.searchVersion | integer | The revision of the search this run ran. |
data.clientId | string (uuid) | null | The search's client, or null for a search that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set run. |
data.execution | object | null | The live execution behind a Homes for sale run; null for a data set run. |
data.execution.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.execution.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.execution.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.execution.stepLabel | string | null | That play in words for a person. |
data.execution.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.execution.progress | object | |
data.execution.progress.done | integer | Plays finished. |
data.execution.progress.total | integer | Plays in a run. |
data.execution.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.execution.startedAt | string (date-time) | null | |
data.execution.finishedAt | string (date-time) | null | |
data.execution.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.execution.error.code | string | |
data.execution.error.digest | string | null | |
data.execution.review | object | null | What the engine's prose review did on this run, as whole-number counts by name: summaryFlagged, summaryRepaired, summaryDropped, summarySectionsRebuilt, proseFlagged, proseRewritten, takesStandIn, repairCalls, and any count a newer engine adds (its verify… counts). Counts only, never the prose. Null when the engine sent none; a run on the built-in engine never has one. |
data.execution.links | object | |
data.execution.links.self | string | |
data.execution.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set run. |
data.counts | object | null | Null until the run is complete. |
data.counts.results | integer | Homes in the results. |
data.counts.removed | integer | Homes the run itself chose that you took out of the results. |
data.counts.excluded | integer | Homes the run graded and left out. |
data.counts.considered | integer | Homes the run weighed. |
data.results | object[] | The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete. |
data.results[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.results[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.results[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.results[].address | string | null | |
data.results[].area | string | null | The city. |
data.results[].state | string | null | |
data.results[].postalCode | string | null | |
data.results[].neighbourhood | string | null | |
data.results[].price | number | null | |
data.results[].beds | number | null | |
data.results[].baths | number | null | |
data.results[].sqft | number | null | |
data.results[].propertyType | string | null | |
data.results[].yearBuilt | integer | null | |
data.results[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.results[].images[].url | string (uri) | |
data.results[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.results[].location | object | null | |
data.results[].location.lat | number | |
data.results[].location.lng | number | |
data.results[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.results[].listedBy.office | string | |
data.results[].listedBy.listingKey | string | |
data.results[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.results[].details.status | string | at least 1 characters |
data.results[].details.yearBuilt | integer | null | |
data.results[].details.lotSqft | number | null | at least 0 |
data.results[].details.garageSpaces | number | null | at least 0 |
data.results[].details.daysOnMarket | integer | null | at least 0 |
data.results[].details.remarks | string | |
data.results[].details.features | string[] | |
data.results[].details.latitude | number | null | -90 to 90 |
data.results[].details.longitude | number | null | -180 to 180 |
data.results[].details.source | string | at least 1 characters |
data.results[].details.sourceUrl | string (uri), optional | |
data.results[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.results[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.results[].scoreParts.math | number | 0 to 100 |
data.results[].scoreParts.text | number | null | 0 to 100 |
data.results[].scoreParts.photos | number | null | 0 to 100 |
data.results[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.results[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.results[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.results[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.results[].highlights | string[] | |
data.results[].concerns | string[] | |
data.results[].lookAndFeel | string | null | |
data.results[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.results[].commutes[].label | string | 1 to 120 characters |
data.results[].commutes[].minutes | integer | 0 to 240 |
data.results[].commutes[].estimated | boolean | |
data.results[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.results[].signals.school | number | null | |
data.results[].signals.safety | number | null | |
data.results[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.results[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.results[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.results[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.removed | object[] | Homes the run itself chose that you took out of the results, in the run's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.excluded | object[] | Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.excluded[].limits | string[] | Each limit the search set that this home passes over, one line each: the budget, a commute's limit, the area searched. Said here and never again in tradeoffs. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the run used. Empty only when everything was live. |
data.emptyReason | object | null | Why a complete run showed no home, and the change summary suggests; null when it showed homes or is still running. |
data.emptyReason.code | string | The gate or step that left no home: nothing_in_the_area, no_listings_fetched, no_photographs, bed_bath_minimums, property_kind, dealbreakers, must_haves, commute_ceilings, or at the shortlist over_budget, kind_unreported, no_home_fits. Read an unknown code as no home fitting. |
data.emptyReason.stage | string | null | The funnel stage it names, or shortlist. |
data.emptyReason.before | integer | null | How many homes reached that gate; null when not counted. |
data.emptyReason.after | integer | null | How many it kept: 0. |
data.compliance | object | object | The Fair Housing checklist, or kind: "not_reviewed" with no items when the review did not run (a run with no homes is never reviewed). It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.search | string | The search it ran. |
data.links.results | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the run's shares. |
data.links.pdf | string | The run as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such run in your workspace. |
| 400 | invalid | A home is named twice, or there are more than twenty; issues names each. |
| 400 | invalid-json | The body is empty or not JSON. |
| 400 | invalid-if-match | The If-Match is not a tag a read returned. |
| 413 | too-large | The body is over 64 KiB. |
| 409 | run-not-ready | The run is still working, or stopped or failed: it has no results yet. |
| 412 | revision-mismatch | The results changed since the tag in If-Match. |
| 422 | unknown-home | An id is not a home this run had. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Download a run as a PDF
/api/v1/runs/{runId}/pdfOne of your runs as a PDF, for your own systems. runId is the run's, or the execution.id of the execution that made it. It prints the run's live share as its client sees it, or, when none is live, the default package: every home in the results, up to twenty, with the cover counting how many of how many when they hold more. Homes for sale print with the Realtracs and MLS GRID credits and their listing offices. X-Pdf-Engine says which engine printed, X-Pdf-Plain: 1 says when it is the plain version, and X-Pdf-Photos: 7/9 says how many photos printed of those wanted. A headless run started with an API key is not one of these, so it has no PDF.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
runId | Path | string (uuid) | Required | The run's id, or the id of the execution that made it. |
Examples
curl "https://liviamatch.com/api/v1/runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The PDF's bytes, as an attachment, with X-Pdf-Engine, X-Pdf-Plain and X-Pdf-Photos.
The bytes, with their own content type.
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such run in your workspace, a headless run, or a malformed id. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Match a brief
/api/v1/searches/{searchId}/matchesProduct path. Runs a search, as it stands, against its source, and answers the match. The match shows up in Searches and Clients, as it does in the app. Against Homes for sale a run works in the background for a minute or two: the answer is 202 with status: "running", a Location (/api/v1/matches/{matchId}) and a Retry-After. Against a data set the match is complete as soon as it is made: the answer is 201 with the shortlist.
A search that names no place still runs. With no area, commute or pin, Homes for sale looks around the org's market, or Nashville, TN while none is set. It counts as a match like any other. A data set's search looks where that data set has the most homes.
Poll the run. A match's id is its run's id: poll GET /api/v1/runs/{matchId} until status is complete, failed or canceled, honoring Retry-After between reads. It answers in the current words, the homes under results. The Location above still names the old path, which answers too. See Runs and polling and the journey.
Send an Idempotency-Key. A network error after you sent the request leaves you not knowing whether a match started, and a second one spends a second match. With the key, a retry answers the match the first one made (Idempotent-Replayed: true) and starts nothing new; the same key for a different brief is 409.
A match counts one against the org's monthly allowance and the person's own limit (GET /api/v1/search/usage says what is left), and is recorded against the key that started it. The match pins the brief revision it ran, so editing the brief later never changes it.
When it's ready. The body is optional. notify says who hears when the match finishes: you (agent.text, agent.email; left out, your profile decides on a Homes for sale match and no one is told on a data set match), the brief's client (client, off unless sent), and up to five more emails or mobile numbers (also). The client and the people named get the public share link by email, and by text when they have a mobile number, only when the Fair Housing review passed or warned; otherwise nothing goes to them and you are told it needs your review. Texts to them wait out 9pm to 8am. Read where each send stands on the match's notify.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
Idempotency-Key | Header | string | Optional | A value of your own for this attempt. The same key with the same request replays the first answer (Idempotent-Replayed: true) and starts nothing new; the same key with a different request is 409. A key is remembered for as long as its run exists. |
Request body
Optional. notify names who hears when the match is ready: you, the client and up to five more (spec 035); notify.callbackUrl asks for a signed callback when it ends, instead of polling: see Get told when a match finishes. A callback needs a key with a signing secret. The body is optional.
Fields (7)
| Field | Type | Required | Description |
|---|---|---|---|
notify | object | Optional | Who hears when the run is ready: you, the client, up to five more, and a callback URL. Left out: your profile decides for you, and no one else hears. |
notify.agent | object | Optional | Tell me: you, by text and by email. |
notify.agent.text | boolean | Optional | Text you when it is ready. Left out: your profile's setting on a Homes for sale match, off on a data set match. |
notify.agent.email | boolean | Optional | Email you when it is ready. Left out: as text. |
notify.client | boolean | Optional | Send the client the share link by email, and by text when they have a mobile number, once the Fair Housing review passes or warns. Off when left out. |
notify.also | string[] | Optional | Up to five more emails or mobile numbers, each sent the share link the same way.at most 5 items |
notify.callbackUrl | string | Optional | 1 to 2000 characters |
{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}Examples
curl -X POST "https://liviamatch.com/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/matches" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Idempotency-Key: okafor-east-nashville-1" \
-H "Content-Type: application/json" \
-d '{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}'Responses
A live run was queued. Read the match until status is not running.
HeadersLocationRetry-AfterETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "running",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:03:11.402Z",
"dataAsOf": null,
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "queued",
"step": null,
"stepLabel": null,
"attempts": 0,
"progress": {
"done": 0,
"total": 9,
"percent": 0
},
"startedAt": null,
"finishedAt": null,
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": null,
"counts": null,
"shortlist": [],
"removed": [],
"excluded": [],
"funnel": null,
"reasonCounts": {},
"credits": [],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
A data set answered at once: the match is complete.
HeadersLocationETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"counts": {
"shortlisted": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"shortlist": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget"
}
],
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid | The body failed validation: an unknown key, more than five notify.also addresses, or one that is neither an email nor a mobile number; issues names each. |
| 400 | invalid-json | The body is not JSON. |
| 400 | invalid-idempotency-key | The Idempotency-Key is malformed. |
| 402 | out-of-credits | The org has no matches left this month. |
| 402 | person-limit-reached | The person the key acts as has used their own monthly matches. |
| 404 | not-found | No such brief in your workspace. |
| 409 | idempotency-key-reused | The Idempotency-Key was used for a different brief. |
| 422 | brief-unrunnable | The brief cannot run against its source as it stands: a place Homes for sale cannot find, a commute or a rental against a data set, no source, or nothing a client asked for. issues says which. |
| 429 | rate-limited | The hourly cap on starting matches is spent (the answer has no RateLimit header). |
| 429 | too-many-active | 3 runs are already queued or running. |
| 503 | search-unavailable | An outside service the match needs is not configured here. |
| 503 | studio-incomplete | A prompt the match engine runs is incomplete in Livia's AI settings; issues names the step. Nothing was started or spent. |
| 400 | invalid | The body is not { notify: { callbackUrl } }, or the URL is not one a callback may use; issues names it. |
| 400 | invalid-json | The body is not JSON. |
| 413 | too-large | The body is over its limit. |
| 422 | callback-url-refused | notify.callbackUrl is plain http to localhost on a deployment that is not development. |
| 422 | callback-needs-key | notify.callbackUrl was named by a signed-in session rather than an API key. |
| 422 | no-signing-secret | notify.callbackUrl was named and the key has no signing secret. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 monthly-cap-reached500 internal
List a brief's matches
/api/v1/searches/{searchId}/matchesThe matches of one brief, newest first, each as a card reads it: where it stands and how many homes it shortlisted, never the homes. Read a match for those. Pages by cursor, 20 at a time and up to 50.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/matches" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of matches.
{
"data": [
{
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"homes": 2,
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15"
}
}
],
"links": {
"next": null
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | |
data[].kind | "dataset" | "market" | |
data[].status | "complete" | "failed" | "running" | "canceled" | |
data[].briefId | string (uuid) | |
data[].briefVersion | integer | |
data[].homes | integer | null | The shortlist's size; null until the match is complete. |
data[].createdAt | string (date-time) | |
data[].updatedAt | string (date-time) | |
data[].links | object | |
data[].links.self | string | |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such brief in your workspace. |
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
List matches
/api/v1/matchesYour matches of both kinds, newest first, each as a card reads it. Pages by cursor, 20 at a time and up to 50: follow links.next until it is null. A run started with POST /api/v1/search has no match and is not listed here.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/matches" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of matches.
{
"data": [
{
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"homes": 2,
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15"
}
}
],
"links": {
"next": null
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | |
data[].kind | "dataset" | "market" | |
data[].status | "complete" | "failed" | "running" | "canceled" | |
data[].briefId | string (uuid) | |
data[].briefVersion | integer | |
data[].homes | integer | null | The shortlist's size; null until the match is complete. |
data[].createdAt | string (date-time) | |
data[].updatedAt | string (date-time) | |
data[].links | object | |
data[].links.self | string | |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Read a match
/api/v1/matches/{matchId}Status and results on one GET. One match: where it stands, and, once status is complete, every home with its score, its parts and its reasons, in the order you curated, plus what it left out and why. To wait for a match, poll GET /api/v1/runs/{matchId} instead: the same run at the same id, in the current words.
While it is running the answer has no homes yet and carries Retry-After: read it again after that many seconds. A run nobody is driving (a crash, a deploy) is picked up again by this read, so keep polling until status is complete, failed or canceled. To stop a Homes for sale match, POST to run.links.cancel; a canceled match stays canceled.
credits and every home's listedBy are attribution a provider's terms and MLS rules require wherever the homes are shown. notes lists every stand-in the match used. compliance is a Fair Housing checklist or "not_reviewed", never a clearance. On a search-run GET, when compliance stayed "not_reviewed", read complianceSkip for why (turned off, not configured, or call-failed after an unusable reviewer reply) — results still return; we never invent a pass. The ETag names the shortlist, for PUT .../shortlist.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
matchId | Path | string (uuid) | Required | The match's id: data.id from the answer that started it. |
Examples
curl "https://liviamatch.com/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The match.
HeadersETagRetry-After
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"counts": {
"shortlisted": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"shortlist": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget"
}
],
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "running",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:03:11.402Z",
"dataAsOf": null,
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "running",
"step": "grade",
"stepLabel": "Reading each home's words and photos",
"attempts": 1,
"progress": {
"done": 6,
"total": 9,
"percent": 71
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": null,
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": null,
"counts": null,
"shortlist": [],
"removed": [],
"excluded": [],
"funnel": null,
"reasonCounts": {},
"credits": [],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such match in your workspace. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Reorder or trim the shortlist
/api/v1/matches/{matchId}/shortlistReplaces the shortlist whole: the homes you name, in that order. That one call removes a home (leave it out), reorders (change the order) and adds one the match left out (name it). Every id must be a homes[].id from this match, each once, up to twenty; an empty list is allowed.
It writes only your list. The match's own result never changes, a home you take off moves to removed with its reasons kept, and a home you add from excluded carries outside, why the match left it out. A share you already sent keeps the homes it was sent with.
Without If-Match the last write wins. Send the ETag of the match you read as If-Match to refuse overwriting a list you have not seen: a list that changed since is 412 and nothing is written.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
matchId | Path | string (uuid) | Required | The match's id: data.id from the answer that started it. |
If-Match | Header | string | Optional | The ETag of the match you read, such as "own" or "3f9a1c7d02ab". If the shortlist has changed since, nothing is written and the answer is 412. |
Request body
The ordered ids of the homes to shortlist.
Fields (1)
| Field | Type | Required | Description |
|---|---|---|---|
homes | string[] | Required | The ids of the homes you want shortlisted, in the order you want them, up to 20, each once. An id is a homes[].id from this match: on the shortlist, taken off it (removed), or left out (excluded). An empty list is allowed.at most 20 items |
{
"homes": [
"NSH-2279012",
"NSH-2283104"
]
}Examples
curl -X PUT "https://liviamatch.com/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"homes": [
"NSH-2279012",
"NSH-2283104"
]
}'Responses
The match, with the shortlist as you arranged it.
HeadersETag
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"counts": {
"shortlisted": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"shortlist": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget"
}
],
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such match in your workspace. |
| 400 | invalid | A home is named twice, or there are more than twenty; issues names each. |
| 400 | invalid-json | The body is empty or not JSON. |
| 400 | invalid-if-match | The If-Match is not a tag a read returned. |
| 413 | too-large | The body is over 64 KiB. |
| 409 | match-not-ready | The match is still running, or stopped or failed: it has no shortlist yet. |
| 412 | revision-mismatch | The shortlist changed since the tag in If-Match. |
| 422 | unknown-home | An id is not a home this match had. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Match a brief
/api/v1/briefs/{searchId}/matchesProduct path. Runs a search, as it stands, against its source, and answers the match. The match shows up in Searches and Clients, as it does in the app. Against Homes for sale a run works in the background for a minute or two: the answer is 202 with status: "running", a Location (/api/v1/matches/{matchId}) and a Retry-After. Against a data set the match is complete as soon as it is made: the answer is 201 with the shortlist.
A search that names no place still runs. With no area, commute or pin, Homes for sale looks around the org's market, or Nashville, TN while none is set. It counts as a match like any other. A data set's search looks where that data set has the most homes.
Poll the run. A match's id is its run's id: poll GET /api/v1/runs/{matchId} until status is complete, failed or canceled, honoring Retry-After between reads. It answers in the current words, the homes under results. The Location above still names the old path, which answers too. See Runs and polling and the journey.
Send an Idempotency-Key. A network error after you sent the request leaves you not knowing whether a match started, and a second one spends a second match. With the key, a retry answers the match the first one made (Idempotent-Replayed: true) and starts nothing new; the same key for a different brief is 409.
A match counts one against the org's monthly allowance and the person's own limit (GET /api/v1/search/usage says what is left), and is recorded against the key that started it. The match pins the brief revision it ran, so editing the brief later never changes it.
When it's ready. The body is optional. notify says who hears when the match finishes: you (agent.text, agent.email; left out, your profile decides on a Homes for sale match and no one is told on a data set match), the brief's client (client, off unless sent), and up to five more emails or mobile numbers (also). The client and the people named get the public share link by email, and by text when they have a mobile number, only when the Fair Housing review passed or warned; otherwise nothing goes to them and you are told it needs your review. Texts to them wait out 9pm to 8am. Read where each send stands on the match's notify.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
Idempotency-Key | Header | string | Optional | A value of your own for this attempt. The same key with the same request replays the first answer (Idempotent-Replayed: true) and starts nothing new; the same key with a different request is 409. A key is remembered for as long as its run exists. |
Request body
Optional. notify names who hears when the match is ready: you, the client and up to five more (spec 035); notify.callbackUrl asks for a signed callback when it ends, instead of polling: see Get told when a match finishes. A callback needs a key with a signing secret. The body is optional.
Fields (7)
| Field | Type | Required | Description |
|---|---|---|---|
notify | object | Optional | Who hears when the run is ready: you, the client, up to five more, and a callback URL. Left out: your profile decides for you, and no one else hears. |
notify.agent | object | Optional | Tell me: you, by text and by email. |
notify.agent.text | boolean | Optional | Text you when it is ready. Left out: your profile's setting on a Homes for sale match, off on a data set match. |
notify.agent.email | boolean | Optional | Email you when it is ready. Left out: as text. |
notify.client | boolean | Optional | Send the client the share link by email, and by text when they have a mobile number, once the Fair Housing review passes or warns. Off when left out. |
notify.also | string[] | Optional | Up to five more emails or mobile numbers, each sent the share link the same way.at most 5 items |
notify.callbackUrl | string | Optional | 1 to 2000 characters |
{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}Examples
curl -X POST "https://liviamatch.com/api/v1/briefs/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/matches" \
-H "Authorization: Bearer $LIVIA_API_KEY" \
-H "Idempotency-Key: okafor-east-nashville-1" \
-H "Content-Type: application/json" \
-d '{
"notify": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": [
"co-buyer@example.com",
"+16155550142"
],
"callbackUrl": "https://hooks.example.com/livia"
}
}'Responses
A live run was queued. Read the match until status is not running.
HeadersLocationRetry-AfterETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "running",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:03:11.402Z",
"dataAsOf": null,
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "queued",
"step": null,
"stepLabel": null,
"attempts": 0,
"progress": {
"done": 0,
"total": 9,
"percent": 0
},
"startedAt": null,
"finishedAt": null,
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": null,
"counts": null,
"shortlist": [],
"removed": [],
"excluded": [],
"funnel": null,
"reasonCounts": {},
"credits": [],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "asked",
"reason": null,
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
A data set answered at once: the match is complete.
HeadersLocationETagIdempotent-Replayed
{
"data": {
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"clientId": "9c4e1a73-2b85-4d06-8f1a-7d3b5e9c0a28",
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"dataAsOf": "2026-10-02T14:05:47.930Z",
"run": {
"id": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"status": "succeeded",
"step": "compliance",
"stepLabel": "Checking fair housing",
"attempts": 1,
"progress": {
"done": 9,
"total": 9,
"percent": 100
},
"startedAt": "2026-10-02T14:03:13.004Z",
"finishedAt": "2026-10-06T14:05:47.930Z",
"error": null,
"links": {
"self": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"cancel": "/api/v1/search/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/executions/0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83/cancel"
}
},
"summary": "Four homes fit the Okafors. **1204 Boscobel St** is the strongest: the yard, the porch and the short commute all land.",
"counts": {
"shortlisted": 2,
"removed": 1,
"excluded": 1,
"considered": 312
},
"shortlist": [
{
"id": "NSH-2283104",
"rank": 1,
"ownRank": 1,
"address": "1204 Boscobel St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 689000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 91.4,
"scoreParts": {
"math": 88.2,
"text": 93,
"photos": 92.5,
"neighbourhood": 90
},
"reasons": [
"Fenced backyard",
"Walkable to two coffee shops",
"Dedicated home office"
],
"tradeoffs": [
"One bathroom is down a hallway from the primary"
],
"take": "A renovated 1926 bungalow with the fenced yard and the porch they asked for, 14 minutes from the hospital.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null
},
{
"id": "NSH-2279012",
"rank": 2,
"ownRank": 2,
"address": "317 Sylvan St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 649000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 86.7,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"removed": [
{
"id": "NSH-2268840",
"rank": null,
"ownRank": 3,
"address": "905 Fatherland St",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 712000,
"beds": 3,
"baths": 2,
"sqft": 1880,
"propertyType": "Residential",
"yearBuilt": 1948,
"images": [
{
"url": "https://photos.example.com/NSH-2279012/hero.jpg"
}
],
"location": {
"lat": 36.1779,
"lng": -86.7351
},
"listedBy": {
"office": "Parkway Realty",
"listingKey": "NSH-2279012"
},
"details": null,
"score": 84.2,
"scoreParts": {
"math": 90.1,
"text": 84,
"photos": 85.5,
"neighbourhood": 87.2
},
"reasons": [
"Under budget with room to spare",
"Fenced yard",
"Five minutes from Five Points"
],
"tradeoffs": [
"Smaller than the first choice"
],
"take": "A tidy 1948 cottage that leaves $100,000 of the budget unspent, with the yard they asked for.",
"highlights": [
"Fresh kitchen"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 18,
"estimated": false
}
],
"signals": {
"school": 74,
"safety": 69
},
"misses": [],
"unconfirmed": [],
"outside": null
}
],
"excluded": [
{
"id": "NSH-2271550",
"rank": null,
"ownRank": null,
"address": "88 Gartland Ave",
"area": "Nashville",
"state": "TN",
"postalCode": "37206",
"neighbourhood": "East Nashville",
"price": 779000,
"beds": 3,
"baths": 2.5,
"sqft": 2140,
"propertyType": "Residential",
"yearBuilt": 1926,
"images": [
{
"url": "https://photos.example.com/NSH-2283104/hero.jpg"
},
{
"url": "https://photos.example.com/NSH-2283104/kitchen.jpg",
"caption": "Kitchen"
}
],
"location": {
"lat": 36.1832,
"lng": -86.7424
},
"listedBy": {
"office": "Hearth & Key Realty",
"listingKey": "NSH-2283104"
},
"details": null,
"score": 66.1,
"scoreParts": {
"math": 61,
"text": 70,
"photos": 68,
"neighbourhood": 66
},
"reasons": [
"Original details"
],
"tradeoffs": [
"Over budget"
],
"take": "A handsome home, just over budget.",
"highlights": [
"Original heart-pine floors",
"Deep front porch"
],
"concerns": [],
"lookAndFeel": "Warm, bright, restored rather than flipped.",
"commutes": [
{
"label": "Vanderbilt University Medical Center",
"minutes": 14,
"estimated": false
}
],
"signals": {
"school": 78,
"safety": 71
},
"misses": [],
"unconfirmed": [
"two-car garage"
],
"outside": null,
"why": [
"Asking $29,000 over the $750,000 budget."
],
"category": "over_budget"
}
],
"funnel": {
"terminalStatus": 12,
"noCoordinates": 3,
"outsideArea": 41,
"duplicates": 6,
"fetched": 312,
"wrongType": 38,
"pooled": 212,
"beyondReach": 57,
"scored": 155,
"graded": 25,
"shortlisted": 4
},
"reasonCounts": {
"Asking $29,000 over the $750,000 budget.": 1
},
"credits": [
{
"text": "Routes by Targomo, map data by OpenStreetMap contributors.",
"url": "https://www.targomo.com"
}
],
"notes": [],
"compliance": "not_reviewed",
"notify": {
"asked": {
"agent": {
"text": true,
"email": false
},
"client": true,
"also": []
},
"recipients": [
{
"audience": "agent",
"channel": "sms",
"to": null,
"state": "sent",
"reason": null,
"sendAfter": null
},
{
"audience": "client",
"channel": "sms",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
},
{
"audience": "client",
"channel": "email",
"to": null,
"state": "held",
"reason": "fair-housing-not-reviewed",
"sendAfter": null
}
]
},
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"brief": "/api/v1/searches/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"shortlist": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shortlist",
"shares": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/shares",
"pdf": "/api/v1/search-runs/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15/pdf"
}
}
}Fields (261)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | |
data.kind | "dataset" | "market" | market ran against Homes for sale through a live run; dataset ran against one of your data sets and was complete as soon as it was made. |
data.status | "complete" | "failed" | "running" | "canceled" | running has no shortlist yet: keep polling. complete, failed and canceled are final. |
data.briefId | string (uuid) | |
data.briefVersion | integer | The revision of the brief this match ran. |
data.clientId | string (uuid) | null | The brief's client, or null for a brief that is nobody's. |
data.createdAt | string (date-time) | |
data.updatedAt | string (date-time) | |
data.dataAsOf | string (date-time) | null | When the listings were read. Null for a data set match. |
data.run | object | null | The live run behind a Homes for sale match; null for a data set match. |
data.run.id | string (uuid) | The run's id, as GET /api/v1/search/{briefId}/executions/{id} reads it. |
data.run.status | "queued" | "running" | "succeeded" | "failed" | "canceled" | queued and running are unfinished. succeeded, failed and canceled are final. |
data.run.step | "area" | "gather" | "weigh" | "score" | "enrich" | "inspire" | "grade" | "finalize" | "compliance" | null | The play the run is on, or null before it starts and after it ends. |
data.run.stepLabel | string | null | That play in words for a person. |
data.run.attempts | integer | How many times a driver has claimed the run. More than one means it resumed after a crash or a deadline. |
data.run.progress | object | |
data.run.progress.done | integer | Plays finished. |
data.run.progress.total | integer | Plays in a run. |
data.run.progress.percent | integer | How far along, 0 to 100.0 to 100 |
data.run.startedAt | string (date-time) | null | |
data.run.finishedAt | string (date-time) | null | |
data.run.error | object | null | Why a run failed, with the digest to quote to us; null otherwise. |
data.run.error.code | string | |
data.run.error.digest | string | null | |
data.run.links | object | |
data.run.links.self | string | |
data.run.links.cancel | string | Where to POST to cancel the run. |
data.summary | string | null | A paragraph on how the homes fit, in markdown. Null for a data set match. |
data.counts | object | null | Null until the match is complete. |
data.counts.shortlisted | integer | Homes on the shortlist. |
data.counts.removed | integer | The match's own shortlisted homes you took off it. |
data.counts.excluded | integer | Homes the match graded and left out. |
data.counts.considered | integer | Homes the match weighed. |
data.shortlist | object[] | The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete. |
data.shortlist[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.shortlist[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.shortlist[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.shortlist[].address | string | null | |
data.shortlist[].area | string | null | The city. |
data.shortlist[].state | string | null | |
data.shortlist[].postalCode | string | null | |
data.shortlist[].neighbourhood | string | null | |
data.shortlist[].price | number | null | |
data.shortlist[].beds | number | null | |
data.shortlist[].baths | number | null | |
data.shortlist[].sqft | number | null | |
data.shortlist[].propertyType | string | null | |
data.shortlist[].yearBuilt | integer | null | |
data.shortlist[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.shortlist[].images[].url | string (uri) | |
data.shortlist[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.shortlist[].location | object | null | |
data.shortlist[].location.lat | number | |
data.shortlist[].location.lng | number | |
data.shortlist[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.shortlist[].listedBy.office | string | |
data.shortlist[].listedBy.listingKey | string | |
data.shortlist[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.shortlist[].details.status | string | at least 1 characters |
data.shortlist[].details.yearBuilt | integer | null | |
data.shortlist[].details.lotSqft | number | null | at least 0 |
data.shortlist[].details.garageSpaces | number | null | at least 0 |
data.shortlist[].details.daysOnMarket | integer | null | at least 0 |
data.shortlist[].details.remarks | string | |
data.shortlist[].details.features | string[] | |
data.shortlist[].details.latitude | number | null | -90 to 90 |
data.shortlist[].details.longitude | number | null | -180 to 180 |
data.shortlist[].details.source | string | at least 1 characters |
data.shortlist[].details.sourceUrl | string (uri), optional | |
data.shortlist[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.shortlist[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.shortlist[].scoreParts.math | number | 0 to 100 |
data.shortlist[].scoreParts.text | number | null | 0 to 100 |
data.shortlist[].scoreParts.photos | number | null | 0 to 100 |
data.shortlist[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.shortlist[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.shortlist[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.shortlist[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.shortlist[].highlights | string[] | |
data.shortlist[].concerns | string[] | |
data.shortlist[].lookAndFeel | string | null | |
data.shortlist[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.shortlist[].commutes[].label | string | 1 to 120 characters |
data.shortlist[].commutes[].minutes | integer | 0 to 240 |
data.shortlist[].commutes[].estimated | boolean | |
data.shortlist[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.shortlist[].signals.school | number | null | |
data.shortlist[].signals.safety | number | null | |
data.shortlist[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.shortlist[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.shortlist[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.removed | object[] | The match's own shortlisted homes you took off the shortlist, in the match's order. |
data.removed[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.removed[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.removed[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.removed[].address | string | null | |
data.removed[].area | string | null | The city. |
data.removed[].state | string | null | |
data.removed[].postalCode | string | null | |
data.removed[].neighbourhood | string | null | |
data.removed[].price | number | null | |
data.removed[].beds | number | null | |
data.removed[].baths | number | null | |
data.removed[].sqft | number | null | |
data.removed[].propertyType | string | null | |
data.removed[].yearBuilt | integer | null | |
data.removed[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.removed[].images[].url | string (uri) | |
data.removed[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.removed[].location | object | null | |
data.removed[].location.lat | number | |
data.removed[].location.lng | number | |
data.removed[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.removed[].listedBy.office | string | |
data.removed[].listedBy.listingKey | string | |
data.removed[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.removed[].details.status | string | at least 1 characters |
data.removed[].details.yearBuilt | integer | null | |
data.removed[].details.lotSqft | number | null | at least 0 |
data.removed[].details.garageSpaces | number | null | at least 0 |
data.removed[].details.daysOnMarket | integer | null | at least 0 |
data.removed[].details.remarks | string | |
data.removed[].details.features | string[] | |
data.removed[].details.latitude | number | null | -90 to 90 |
data.removed[].details.longitude | number | null | -180 to 180 |
data.removed[].details.source | string | at least 1 characters |
data.removed[].details.sourceUrl | string (uri), optional | |
data.removed[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.removed[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.removed[].scoreParts.math | number | 0 to 100 |
data.removed[].scoreParts.text | number | null | 0 to 100 |
data.removed[].scoreParts.photos | number | null | 0 to 100 |
data.removed[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.removed[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.removed[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.removed[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.removed[].highlights | string[] | |
data.removed[].concerns | string[] | |
data.removed[].lookAndFeel | string | null | |
data.removed[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.removed[].commutes[].label | string | 1 to 120 characters |
data.removed[].commutes[].minutes | integer | 0 to 240 |
data.removed[].commutes[].estimated | boolean | |
data.removed[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.removed[].signals.school | number | null | |
data.removed[].signals.safety | number | null | |
data.removed[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.removed[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.removed[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded | object[] | Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number. |
data.excluded[].id | string | The home's id: a data set listing's id, or a Homes for sale listing key. What PUT .../shortlist and a share name. |
data.excluded[].rank | integer | null | Its place on the shortlist, 1 first; null for a home that is not on it.at least 1 |
data.excluded[].ownRank | integer | null | Where the match itself put it, whatever the order is now; null for a home the match left out.at least 1 |
data.excluded[].address | string | null | |
data.excluded[].area | string | null | The city. |
data.excluded[].state | string | null | |
data.excluded[].postalCode | string | null | |
data.excluded[].neighbourhood | string | null | |
data.excluded[].price | number | null | |
data.excluded[].beds | number | null | |
data.excluded[].baths | number | null | |
data.excluded[].sqft | number | null | |
data.excluded[].propertyType | string | null | |
data.excluded[].yearBuilt | integer | null | |
data.excluded[].images | object[] | The hero first, then the rooms worth opening with their labels, then the gallery. |
data.excluded[].images[].url | string (uri) | |
data.excluded[].images[].caption | string, optional | The room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one. |
data.excluded[].location | object | null | |
data.excluded[].location.lat | number | |
data.excluded[].location.lng | number | |
data.excluded[].listedBy | object | null | The listing office, which MLS rules require beside a home; null for a data set home. |
data.excluded[].listedBy.office | string | |
data.excluded[].listedBy.listingKey | string | |
data.excluded[].details | object | null | A data set home's stored details; null for a Homes for sale home. |
data.excluded[].details.status | string | at least 1 characters |
data.excluded[].details.yearBuilt | integer | null | |
data.excluded[].details.lotSqft | number | null | at least 0 |
data.excluded[].details.garageSpaces | number | null | at least 0 |
data.excluded[].details.daysOnMarket | integer | null | at least 0 |
data.excluded[].details.remarks | string | |
data.excluded[].details.features | string[] | |
data.excluded[].details.latitude | number | null | -90 to 90 |
data.excluded[].details.longitude | number | null | -180 to 180 |
data.excluded[].details.source | string | at least 1 characters |
data.excluded[].details.sourceUrl | string (uri), optional | |
data.excluded[].score | number | null | The blended score, 0 to 100 for Homes for sale. Null when the match did not score it. |
data.excluded[].scoreParts | object | null | The four parts of the score, each 0 to 100, or null when that part was not measured. Null for a data set home. |
data.excluded[].scoreParts.math | number | 0 to 100 |
data.excluded[].scoreParts.text | number | null | 0 to 100 |
data.excluded[].scoreParts.photos | number | null | 0 to 100 |
data.excluded[].scoreParts.neighbourhood | number | null | 0 to 100 |
data.excluded[].reasons | string[] | Why it fits: a data set home's reasons, or a Homes for sale home's pros. |
data.excluded[].tradeoffs | string[] | What it gives up: a data set home's trade-offs, or a Homes for sale home's cons. |
data.excluded[].take | string | null | One sentence on the home. Null on a data set home, which is not graded. |
data.excluded[].highlights | string[] | |
data.excluded[].concerns | string[] | |
data.excluded[].lookAndFeel | string | null | |
data.excluded[].commutes | object[] | Minutes to each place the brief named, and whether they were estimated rather than routed. |
data.excluded[].commutes[].label | string | 1 to 120 characters |
data.excluded[].commutes[].minutes | integer | 0 to 240 |
data.excluded[].commutes[].estimated | boolean | |
data.excluded[].signals | object | null | What the web read of its neighborhood; null when none turned up. |
data.excluded[].signals.school | number | null | |
data.excluded[].signals.safety | number | null | |
data.excluded[].misses | any[] | A near miss's must-haves it misses, on a data set shortlist. |
data.excluded[].unconfirmed | string[] | The buyer's must-haves this listing never confirms, in their words. |
data.excluded[].outside | string[] | null | Why the match left it out, when you added it to the shortlist from outside it; null otherwise. Always null in excluded, whose reasons are each home's why. |
data.excluded[].why | string[] | Every reason it was left out. |
data.excluded[].category | string | null | The kind of reason, when the run named one. |
data.funnel | object | null | How many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match. |
data.funnel.fetched | number | |
data.funnel.terminalStatus | number | default 0 |
data.funnel.noCoordinates | number | default 0 |
data.funnel.outsideArea | number | default 0 |
data.funnel.duplicates | number | default 0 |
data.funnel.wrongType | number | default 0 |
data.funnel.pooled | number | |
data.funnel.beyondReach | number | default 0 |
data.funnel.scored | number | |
data.funnel.graded | number | |
data.funnel.shortlisted | number | |
data.reasonCounts | object | How many homes each exclusion reason cost. |
data.credits | object[] | Attribution a provider's terms require wherever the homes are shown. |
data.credits[].text | string | |
data.credits[].url | string | |
data.notes | string[] | Every stand-in the match used. Empty only when everything was live. |
data.compliance | "not_reviewed" | object | "not_reviewed" when the review did not run, else its checklist. It flags risk and is never legal clearance; never present it as one. |
data.compliance.kind | "checklist" | |
data.compliance.overall | "pass" | "warn" | "fail" | "needs_human" | |
data.compliance.items | object[] | |
data.compliance.items[].id | string | |
data.compliance.items[].status | "pass" | "warn" | "fail" | "info" | |
data.compliance.items[].detail | string | |
data.compliance.items[].check | string | |
data.compliance.items[].evidence | object[] | default [] |
data.compliance.items[].evidence[].source | string | |
data.compliance.items[].evidence[].listingKey | string | null | |
data.compliance.items[].evidence[].excerpt | string | |
data.compliance.reviewedAt | string | |
data.compliance.source | "model" | "stand-in" | |
data.notify | object | null | Who hears when it is ready, and where each send stands. Null when nothing was asked. |
data.notify.asked | object | |
data.notify.asked.agent | object | Tell me: you, by text and by email. |
data.notify.asked.agent.text | boolean | |
data.notify.asked.agent.email | boolean | |
data.notify.asked.client | boolean | Send the client the share link once the Fair Housing review passes or warns. |
data.notify.asked.also | string[] | The other addresses named, masked. |
data.notify.recipients | object[] | One line per recipient and channel. |
data.notify.recipients[].audience | "agent" | "client" | "also" | agent is you, client the brief's client, also an address you named. |
data.notify.recipients[].channel | "sms" | "email" | |
data.notify.recipients[].to | string | null | A named address, masked; null for you and the client. |
data.notify.recipients[].state | "asked" | "pending" | "sent" | "held" | "skipped" | "failed" | asked until the match is ready. held means the Fair Housing review did not pass: nothing went to the client or the people named, and you were told. |
data.notify.recipients[].reason | string | null | Why it was held, skipped, failed or is waiting: fair-housing-fail, fair-housing-needs-human, fair-housing-not-reviewed, no-client, no-email, no-phone, opted-out, quiet-hours, no-homes, match-gone, provider-refused, send-failed, maybe-sent, link-failed. Null otherwise. |
data.notify.recipients[].sendAfter | string (date-time) | null | When a text waiting out quiet hours goes. |
data.links | object | |
data.links.self | string | |
data.links.brief | string | The brief it ran. |
data.links.shortlist | string | Where to PUT the ordered list. |
data.links.shares | string | Where to POST a share and GET the match's shares. |
data.links.pdf | string | The match as a PDF (needs search:read). |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid | The body failed validation: an unknown key, more than five notify.also addresses, or one that is neither an email nor a mobile number; issues names each. |
| 400 | invalid-json | The body is not JSON. |
| 400 | invalid-idempotency-key | The Idempotency-Key is malformed. |
| 402 | out-of-credits | The org has no matches left this month. |
| 402 | person-limit-reached | The person the key acts as has used their own monthly matches. |
| 404 | not-found | No such brief in your workspace. |
| 409 | idempotency-key-reused | The Idempotency-Key was used for a different brief. |
| 422 | brief-unrunnable | The brief cannot run against its source as it stands: a place Homes for sale cannot find, a commute or a rental against a data set, no source, or nothing a client asked for. issues says which. |
| 429 | rate-limited | The hourly cap on starting matches is spent (the answer has no RateLimit header). |
| 429 | too-many-active | 3 runs are already queued or running. |
| 503 | search-unavailable | An outside service the match needs is not configured here. |
| 503 | studio-incomplete | A prompt the match engine runs is incomplete in Livia's AI settings; issues names the step. Nothing was started or spent. |
| 400 | invalid | The body is not { notify: { callbackUrl } }, or the URL is not one a callback may use; issues names it. |
| 400 | invalid-json | The body is not JSON. |
| 413 | too-large | The body is over its limit. |
| 422 | callback-url-refused | notify.callbackUrl is plain http to localhost on a deployment that is not development. |
| 422 | callback-needs-key | notify.callbackUrl was named by a signed-in session rather than an API key. |
| 422 | no-signing-secret | notify.callbackUrl was named and the key has no signing secret. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 monthly-cap-reached500 internal
List a brief's matches
/api/v1/briefs/{searchId}/matchesThe matches of one brief, newest first, each as a card reads it: where it stands and how many homes it shortlisted, never the homes. Read a match for those. Pages by cursor, 20 at a time and up to 50.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
searchId | Path | string (uuid) | Required | The search's id. |
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/briefs/7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592/matches" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of matches.
{
"data": [
{
"id": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"kind": "market",
"status": "complete",
"briefId": "7d2f8a40-b6c1-4e35-9a07-c4e1d8b3f592",
"briefVersion": 1,
"homes": 2,
"createdAt": "2026-10-06T14:03:11.402Z",
"updatedAt": "2026-10-06T14:05:47.930Z",
"links": {
"self": "/api/v1/matches/1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15"
}
}
],
"links": {
"next": null
}
}Fields (13)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | |
data[].kind | "dataset" | "market" | |
data[].status | "complete" | "failed" | "running" | "canceled" | |
data[].briefId | string (uuid) | |
data[].briefVersion | integer | |
data[].homes | integer | null | The shortlist's size; null until the match is complete. |
data[].createdAt | string (date-time) | |
data[].updatedAt | string (date-time) | |
data[].links | object | |
data[].links.self | string | |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such brief in your workspace. |
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal