Skip to the documentation

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

POST/api/v1/searches/{searchId}/runs

Runs 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
Idempotency-KeyHeaderstringOptionalA 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)
FieldTypeRequiredDescription
notifyobjectOptionalWho 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.agentobjectOptionalTell me: you, by text and by email.
notify.agent.textbooleanOptionalText 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.emailbooleanOptionalEmail you when it is ready. Left out: as text.
notify.clientbooleanOptionalSend 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.alsostring[]OptionalUp to five more emails or mobile numbers, each sent the share link the same way.at most 5 items
notify.callbackUrlstringOptional1 to 2000 characters
Examples
{
  "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

202

A live execution was queued. Read the run until status is not running.

HeadersLocationRetry-AfterETagIdempotent-Replayed

A run, just queued
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.searchIdstring (uuid)
data.searchVersionintegerThe revision of the search this run ran.
data.clientIdstring (uuid) | nullThe search's client, or null for a search that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set run.
data.executionobject | nullThe live execution behind a Homes for sale run; null for a data set run.
data.execution.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.execution.stepLabelstring | nullThat play in words for a person.
data.execution.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.execution.progressobject
data.execution.progress.doneintegerPlays finished.
data.execution.progress.totalintegerPlays in a run.
data.execution.progress.percentintegerHow far along, 0 to 100.0 to 100
data.execution.startedAtstring (date-time) | null
data.execution.finishedAtstring (date-time) | null
data.execution.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.execution.error.codestring
data.execution.error.digeststring | null
data.execution.reviewobject | nullWhat 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.linksobject
data.execution.links.selfstring
data.execution.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set run.
data.countsobject | nullNull until the run is complete.
data.counts.resultsintegerHomes in the results.
data.counts.removedintegerHomes the run itself chose that you took out of the results.
data.counts.excludedintegerHomes the run graded and left out.
data.counts.consideredintegerHomes the run weighed.
data.resultsobject[]The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete.
data.results[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.results[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.results[].addressstring | null
data.results[].areastring | nullThe city.
data.results[].statestring | null
data.results[].postalCodestring | null
data.results[].neighbourhoodstring | null
data.results[].pricenumber | null
data.results[].bedsnumber | null
data.results[].bathsnumber | null
data.results[].sqftnumber | null
data.results[].propertyTypestring | null
data.results[].yearBuiltinteger | null
data.results[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.results[].images[].urlstring (uri)
data.results[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.results[].locationobject | null
data.results[].location.latnumber
data.results[].location.lngnumber
data.results[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.results[].listedBy.officestring
data.results[].listedBy.listingKeystring
data.results[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.results[].details.statusstringat least 1 characters
data.results[].details.yearBuiltinteger | null
data.results[].details.lotSqftnumber | nullat least 0
data.results[].details.garageSpacesnumber | nullat least 0
data.results[].details.daysOnMarketinteger | nullat least 0
data.results[].details.remarksstring
data.results[].details.featuresstring[]
data.results[].details.latitudenumber | null-90 to 90
data.results[].details.longitudenumber | null-180 to 180
data.results[].details.sourcestringat least 1 characters
data.results[].details.sourceUrlstring (uri), optional
data.results[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.results[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.results[].scoreParts.textnumber | null0 to 100
data.results[].scoreParts.photosnumber | null0 to 100
data.results[].scoreParts.neighbourhoodnumber | null0 to 100
data.results[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.results[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.results[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.results[].highlightsstring[]
data.results[].concernsstring[]
data.results[].lookAndFeelstring | null
data.results[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.results[].commutes[].labelstring1 to 120 characters
data.results[].commutes[].minutesinteger0 to 240
data.results[].commutes[].estimatedboolean
data.results[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.results[].signals.schoolnumber | null
data.results[].signals.safetynumber | null
data.results[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.results[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.results[].outsidestring[] | nullWhy 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[].limitsstring[]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.removedobject[]Homes the run itself chose that you took out of the results, in the run's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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[].limitsstring[]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.excludedobject[]Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.excluded[].limitsstring[]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.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]Every stand-in the run used. Empty only when everything was live.
data.emptyReasonobject | nullWhy a complete run showed no home, and the change summary suggests; null when it showed homes or is still running.
data.emptyReason.codestringThe 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.stagestring | nullThe funnel stage it names, or shortlist.
data.emptyReason.beforeinteger | nullHow many homes reached that gate; null when not counted.
data.emptyReason.afterinteger | nullHow many it kept: 0.
data.complianceobject | objectThe 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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.searchstringThe search it ran.
data.links.resultsstringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the run's shares.
data.links.pdfstringThe run as a PDF (needs search:read).
201

A data set answered at once: the run is complete.

HeadersLocationETagIdempotent-Replayed

A complete run
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.searchIdstring (uuid)
data.searchVersionintegerThe revision of the search this run ran.
data.clientIdstring (uuid) | nullThe search's client, or null for a search that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set run.
data.executionobject | nullThe live execution behind a Homes for sale run; null for a data set run.
data.execution.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.execution.stepLabelstring | nullThat play in words for a person.
data.execution.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.execution.progressobject
data.execution.progress.doneintegerPlays finished.
data.execution.progress.totalintegerPlays in a run.
data.execution.progress.percentintegerHow far along, 0 to 100.0 to 100
data.execution.startedAtstring (date-time) | null
data.execution.finishedAtstring (date-time) | null
data.execution.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.execution.error.codestring
data.execution.error.digeststring | null
data.execution.reviewobject | nullWhat 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.linksobject
data.execution.links.selfstring
data.execution.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set run.
data.countsobject | nullNull until the run is complete.
data.counts.resultsintegerHomes in the results.
data.counts.removedintegerHomes the run itself chose that you took out of the results.
data.counts.excludedintegerHomes the run graded and left out.
data.counts.consideredintegerHomes the run weighed.
data.resultsobject[]The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete.
data.results[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.results[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.results[].addressstring | null
data.results[].areastring | nullThe city.
data.results[].statestring | null
data.results[].postalCodestring | null
data.results[].neighbourhoodstring | null
data.results[].pricenumber | null
data.results[].bedsnumber | null
data.results[].bathsnumber | null
data.results[].sqftnumber | null
data.results[].propertyTypestring | null
data.results[].yearBuiltinteger | null
data.results[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.results[].images[].urlstring (uri)
data.results[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.results[].locationobject | null
data.results[].location.latnumber
data.results[].location.lngnumber
data.results[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.results[].listedBy.officestring
data.results[].listedBy.listingKeystring
data.results[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.results[].details.statusstringat least 1 characters
data.results[].details.yearBuiltinteger | null
data.results[].details.lotSqftnumber | nullat least 0
data.results[].details.garageSpacesnumber | nullat least 0
data.results[].details.daysOnMarketinteger | nullat least 0
data.results[].details.remarksstring
data.results[].details.featuresstring[]
data.results[].details.latitudenumber | null-90 to 90
data.results[].details.longitudenumber | null-180 to 180
data.results[].details.sourcestringat least 1 characters
data.results[].details.sourceUrlstring (uri), optional
data.results[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.results[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.results[].scoreParts.textnumber | null0 to 100
data.results[].scoreParts.photosnumber | null0 to 100
data.results[].scoreParts.neighbourhoodnumber | null0 to 100
data.results[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.results[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.results[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.results[].highlightsstring[]
data.results[].concernsstring[]
data.results[].lookAndFeelstring | null
data.results[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.results[].commutes[].labelstring1 to 120 characters
data.results[].commutes[].minutesinteger0 to 240
data.results[].commutes[].estimatedboolean
data.results[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.results[].signals.schoolnumber | null
data.results[].signals.safetynumber | null
data.results[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.results[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.results[].outsidestring[] | nullWhy 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[].limitsstring[]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.removedobject[]Homes the run itself chose that you took out of the results, in the run's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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[].limitsstring[]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.excludedobject[]Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.excluded[].limitsstring[]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.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]Every stand-in the run used. Empty only when everything was live.
data.emptyReasonobject | nullWhy a complete run showed no home, and the change summary suggests; null when it showed homes or is still running.
data.emptyReason.codestringThe 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.stagestring | nullThe funnel stage it names, or shortlist.
data.emptyReason.beforeinteger | nullHow many homes reached that gate; null when not counted.
data.emptyReason.afterinteger | nullHow many it kept: 0.
data.complianceobject | objectThe 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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.searchstringThe search it ran.
data.links.resultsstringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the run's shares.
data.links.pdfstringThe run as a PDF (needs search:read).

Errors

StatusCodeWhen
400invalidThe 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.
400invalid-jsonThe body is not JSON.
400invalid-idempotency-keyThe Idempotency-Key is malformed.
402out-of-creditsThe org has no runs left this month.
402person-limit-reachedThe person the key acts as has used their own monthly runs.
404not-foundNo such search in your workspace.
409idempotency-key-reusedThe Idempotency-Key was used for a different search.
413too-largeThe body is over its limit.
422search-unrunnableThe 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.
422callback-url-refusednotify.callbackUrl is plain http to localhost on a deployment that is not development.
422callback-needs-keynotify.callbackUrl was named by a signed-in session rather than an API key.
422no-signing-secretnotify.callbackUrl was named and the key has no signing secret.
429rate-limitedThe hourly cap on starting runs is spent (the answer has no RateLimit header).
429too-many-active3 runs are already queued or running.
503search-unavailableAn outside service the run needs is not configured here.
503studio-incompleteA 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

GET/api/v1/searches/{searchId}/runs

The 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
limitQueryintegerOptionalHow many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored.
cursorQuerystringOptionalWhere 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

200

One page of runs.

One run
{
  "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)
FieldTypeDescription
dataobject[]
data[].idstring (uuid)
data[].kind"dataset" | "market"
data[].status"complete" | "failed" | "running" | "canceled"
data[].searchIdstring (uuid)
data[].searchVersioninteger
data[].homesinteger | nullHow many homes are in the results; null until the run is complete.
data[].createdAtstring (date-time)
data[].updatedAtstring (date-time)
data[].linksobject
data[].links.selfstring
linksobject
links.nextstring | nullThe URL of the next page, or null when this is the last. Follow it as given.

Errors

StatusCodeWhen
404not-foundNo such search in your workspace.
400invalid-cursorThe 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

GET/api/v1/runs

Your 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

NameInTypeRequiredDescription
limitQueryintegerOptionalHow many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored.
cursorQuerystringOptionalWhere 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

200

One page of runs.

One run
{
  "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)
FieldTypeDescription
dataobject[]
data[].idstring (uuid)
data[].kind"dataset" | "market"
data[].status"complete" | "failed" | "running" | "canceled"
data[].searchIdstring (uuid)
data[].searchVersioninteger
data[].homesinteger | nullHow many homes are in the results; null until the run is complete.
data[].createdAtstring (date-time)
data[].updatedAtstring (date-time)
data[].linksobject
data[].links.selfstring
linksobject
links.nextstring | nullThe URL of the next page, or null when this is the last. Follow it as given.

Errors

StatusCodeWhen
400invalid-cursorThe 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

GET/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

NameInTypeRequiredDescription
runIdPathstring (uuid)RequiredThe 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

200

The run.

HeadersETagRetry-After

A complete run
{
  "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"
    }
  }
}
A run still working
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.searchIdstring (uuid)
data.searchVersionintegerThe revision of the search this run ran.
data.clientIdstring (uuid) | nullThe search's client, or null for a search that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set run.
data.executionobject | nullThe live execution behind a Homes for sale run; null for a data set run.
data.execution.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.execution.stepLabelstring | nullThat play in words for a person.
data.execution.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.execution.progressobject
data.execution.progress.doneintegerPlays finished.
data.execution.progress.totalintegerPlays in a run.
data.execution.progress.percentintegerHow far along, 0 to 100.0 to 100
data.execution.startedAtstring (date-time) | null
data.execution.finishedAtstring (date-time) | null
data.execution.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.execution.error.codestring
data.execution.error.digeststring | null
data.execution.reviewobject | nullWhat 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.linksobject
data.execution.links.selfstring
data.execution.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set run.
data.countsobject | nullNull until the run is complete.
data.counts.resultsintegerHomes in the results.
data.counts.removedintegerHomes the run itself chose that you took out of the results.
data.counts.excludedintegerHomes the run graded and left out.
data.counts.consideredintegerHomes the run weighed.
data.resultsobject[]The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete.
data.results[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.results[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.results[].addressstring | null
data.results[].areastring | nullThe city.
data.results[].statestring | null
data.results[].postalCodestring | null
data.results[].neighbourhoodstring | null
data.results[].pricenumber | null
data.results[].bedsnumber | null
data.results[].bathsnumber | null
data.results[].sqftnumber | null
data.results[].propertyTypestring | null
data.results[].yearBuiltinteger | null
data.results[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.results[].images[].urlstring (uri)
data.results[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.results[].locationobject | null
data.results[].location.latnumber
data.results[].location.lngnumber
data.results[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.results[].listedBy.officestring
data.results[].listedBy.listingKeystring
data.results[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.results[].details.statusstringat least 1 characters
data.results[].details.yearBuiltinteger | null
data.results[].details.lotSqftnumber | nullat least 0
data.results[].details.garageSpacesnumber | nullat least 0
data.results[].details.daysOnMarketinteger | nullat least 0
data.results[].details.remarksstring
data.results[].details.featuresstring[]
data.results[].details.latitudenumber | null-90 to 90
data.results[].details.longitudenumber | null-180 to 180
data.results[].details.sourcestringat least 1 characters
data.results[].details.sourceUrlstring (uri), optional
data.results[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.results[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.results[].scoreParts.textnumber | null0 to 100
data.results[].scoreParts.photosnumber | null0 to 100
data.results[].scoreParts.neighbourhoodnumber | null0 to 100
data.results[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.results[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.results[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.results[].highlightsstring[]
data.results[].concernsstring[]
data.results[].lookAndFeelstring | null
data.results[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.results[].commutes[].labelstring1 to 120 characters
data.results[].commutes[].minutesinteger0 to 240
data.results[].commutes[].estimatedboolean
data.results[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.results[].signals.schoolnumber | null
data.results[].signals.safetynumber | null
data.results[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.results[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.results[].outsidestring[] | nullWhy 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[].limitsstring[]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.removedobject[]Homes the run itself chose that you took out of the results, in the run's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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[].limitsstring[]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.excludedobject[]Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.excluded[].limitsstring[]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.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]Every stand-in the run used. Empty only when everything was live.
data.emptyReasonobject | nullWhy a complete run showed no home, and the change summary suggests; null when it showed homes or is still running.
data.emptyReason.codestringThe 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.stagestring | nullThe funnel stage it names, or shortlist.
data.emptyReason.beforeinteger | nullHow many homes reached that gate; null when not counted.
data.emptyReason.afterinteger | nullHow many it kept: 0.
data.complianceobject | objectThe 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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.searchstringThe search it ran.
data.links.resultsstringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the run's shares.
data.links.pdfstringThe run as a PDF (needs search:read).

Errors

StatusCodeWhen
404not-foundNo 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

PUT/api/v1/runs/{runId}/results

Replaces 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

NameInTypeRequiredDescription
runIdPathstring (uuid)RequiredThe run's id: data.id from the answer that started it.
If-MatchHeaderstringOptionalThe 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)
FieldTypeRequiredDescription
homesstring[]RequiredThe 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
Examples
{
  "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

200

The run, with the results as you arranged them.

HeadersETag

Reordered
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.searchIdstring (uuid)
data.searchVersionintegerThe revision of the search this run ran.
data.clientIdstring (uuid) | nullThe search's client, or null for a search that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set run.
data.executionobject | nullThe live execution behind a Homes for sale run; null for a data set run.
data.execution.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.execution.stepLabelstring | nullThat play in words for a person.
data.execution.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.execution.progressobject
data.execution.progress.doneintegerPlays finished.
data.execution.progress.totalintegerPlays in a run.
data.execution.progress.percentintegerHow far along, 0 to 100.0 to 100
data.execution.startedAtstring (date-time) | null
data.execution.finishedAtstring (date-time) | null
data.execution.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.execution.error.codestring
data.execution.error.digeststring | null
data.execution.reviewobject | nullWhat 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.linksobject
data.execution.links.selfstring
data.execution.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set run.
data.countsobject | nullNull until the run is complete.
data.counts.resultsintegerHomes in the results.
data.counts.removedintegerHomes the run itself chose that you took out of the results.
data.counts.excludedintegerHomes the run graded and left out.
data.counts.consideredintegerHomes the run weighed.
data.resultsobject[]The homes that fit, in the order you curated, else the run's own order. Empty until the run is complete.
data.results[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.results[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.results[].addressstring | null
data.results[].areastring | nullThe city.
data.results[].statestring | null
data.results[].postalCodestring | null
data.results[].neighbourhoodstring | null
data.results[].pricenumber | null
data.results[].bedsnumber | null
data.results[].bathsnumber | null
data.results[].sqftnumber | null
data.results[].propertyTypestring | null
data.results[].yearBuiltinteger | null
data.results[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.results[].images[].urlstring (uri)
data.results[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.results[].locationobject | null
data.results[].location.latnumber
data.results[].location.lngnumber
data.results[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.results[].listedBy.officestring
data.results[].listedBy.listingKeystring
data.results[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.results[].details.statusstringat least 1 characters
data.results[].details.yearBuiltinteger | null
data.results[].details.lotSqftnumber | nullat least 0
data.results[].details.garageSpacesnumber | nullat least 0
data.results[].details.daysOnMarketinteger | nullat least 0
data.results[].details.remarksstring
data.results[].details.featuresstring[]
data.results[].details.latitudenumber | null-90 to 90
data.results[].details.longitudenumber | null-180 to 180
data.results[].details.sourcestringat least 1 characters
data.results[].details.sourceUrlstring (uri), optional
data.results[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.results[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.results[].scoreParts.textnumber | null0 to 100
data.results[].scoreParts.photosnumber | null0 to 100
data.results[].scoreParts.neighbourhoodnumber | null0 to 100
data.results[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.results[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.results[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.results[].highlightsstring[]
data.results[].concernsstring[]
data.results[].lookAndFeelstring | null
data.results[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.results[].commutes[].labelstring1 to 120 characters
data.results[].commutes[].minutesinteger0 to 240
data.results[].commutes[].estimatedboolean
data.results[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.results[].signals.schoolnumber | null
data.results[].signals.safetynumber | null
data.results[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.results[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.results[].outsidestring[] | nullWhy 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[].limitsstring[]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.removedobject[]Homes the run itself chose that you took out of the results, in the run's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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[].limitsstring[]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.excludedobject[]Homes the run left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.excluded[].limitsstring[]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.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the results. Null for a data set run.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]Every stand-in the run used. Empty only when everything was live.
data.emptyReasonobject | nullWhy a complete run showed no home, and the change summary suggests; null when it showed homes or is still running.
data.emptyReason.codestringThe 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.stagestring | nullThe funnel stage it names, or shortlist.
data.emptyReason.beforeinteger | nullHow many homes reached that gate; null when not counted.
data.emptyReason.afterinteger | nullHow many it kept: 0.
data.complianceobject | objectThe 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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.searchstringThe search it ran.
data.links.resultsstringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the run's shares.
data.links.pdfstringThe run as a PDF (needs search:read).

Errors

StatusCodeWhen
404not-foundNo such run in your workspace.
400invalidA home is named twice, or there are more than twenty; issues names each.
400invalid-jsonThe body is empty or not JSON.
400invalid-if-matchThe If-Match is not a tag a read returned.
413too-largeThe body is over 64 KiB.
409run-not-readyThe run is still working, or stopped or failed: it has no results yet.
412revision-mismatchThe results changed since the tag in If-Match.
422unknown-homeAn 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

GET/api/v1/runs/{runId}/pdf

One 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

NameInTypeRequiredDescription
runIdPathstring (uuid)RequiredThe 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

200

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

StatusCodeWhen
404not-foundNo 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

POST/api/v1/searches/{searchId}/matches

Product 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
Idempotency-KeyHeaderstringOptionalA 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)
FieldTypeRequiredDescription
notifyobjectOptionalWho 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.agentobjectOptionalTell me: you, by text and by email.
notify.agent.textbooleanOptionalText 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.emailbooleanOptionalEmail you when it is ready. Left out: as text.
notify.clientbooleanOptionalSend 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.alsostring[]OptionalUp to five more emails or mobile numbers, each sent the share link the same way.at most 5 items
notify.callbackUrlstringOptional1 to 2000 characters
Examples
{
  "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

202

A live run was queued. Read the match until status is not running.

HeadersLocationRetry-AfterETagIdempotent-Replayed

A match, just queued
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).
201

A data set answered at once: the match is complete.

HeadersLocationETagIdempotent-Replayed

A complete match
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).

Errors

StatusCodeWhen
400invalidThe 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.
400invalid-jsonThe body is not JSON.
400invalid-idempotency-keyThe Idempotency-Key is malformed.
402out-of-creditsThe org has no matches left this month.
402person-limit-reachedThe person the key acts as has used their own monthly matches.
404not-foundNo such brief in your workspace.
409idempotency-key-reusedThe Idempotency-Key was used for a different brief.
422brief-unrunnableThe 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.
429rate-limitedThe hourly cap on starting matches is spent (the answer has no RateLimit header).
429too-many-active3 runs are already queued or running.
503search-unavailableAn outside service the match needs is not configured here.
503studio-incompleteA prompt the match engine runs is incomplete in Livia's AI settings; issues names the step. Nothing was started or spent.
400invalidThe body is not { notify: { callbackUrl } }, or the URL is not one a callback may use; issues names it.
400invalid-jsonThe body is not JSON.
413too-largeThe body is over its limit.
422callback-url-refusednotify.callbackUrl is plain http to localhost on a deployment that is not development.
422callback-needs-keynotify.callbackUrl was named by a signed-in session rather than an API key.
422no-signing-secretnotify.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

GET/api/v1/searches/{searchId}/matches

The 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
limitQueryintegerOptionalHow many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored.
cursorQuerystringOptionalWhere 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

200

One page of matches.

One match
{
  "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)
FieldTypeDescription
dataobject[]
data[].idstring (uuid)
data[].kind"dataset" | "market"
data[].status"complete" | "failed" | "running" | "canceled"
data[].briefIdstring (uuid)
data[].briefVersioninteger
data[].homesinteger | nullThe shortlist's size; null until the match is complete.
data[].createdAtstring (date-time)
data[].updatedAtstring (date-time)
data[].linksobject
data[].links.selfstring
linksobject
links.nextstring | nullThe URL of the next page, or null when this is the last. Follow it as given.

Errors

StatusCodeWhen
404not-foundNo such brief in your workspace.
400invalid-cursorThe 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

GET/api/v1/matches

Your 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

NameInTypeRequiredDescription
limitQueryintegerOptionalHow many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored.
cursorQuerystringOptionalWhere 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

200

One page of matches.

One match
{
  "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)
FieldTypeDescription
dataobject[]
data[].idstring (uuid)
data[].kind"dataset" | "market"
data[].status"complete" | "failed" | "running" | "canceled"
data[].briefIdstring (uuid)
data[].briefVersioninteger
data[].homesinteger | nullThe shortlist's size; null until the match is complete.
data[].createdAtstring (date-time)
data[].updatedAtstring (date-time)
data[].linksobject
data[].links.selfstring
linksobject
links.nextstring | nullThe URL of the next page, or null when this is the last. Follow it as given.

Errors

StatusCodeWhen
400invalid-cursorThe 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

GET/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

NameInTypeRequiredDescription
matchIdPathstring (uuid)RequiredThe 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

200

The match.

HeadersETagRetry-After

A complete match
{
  "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"
    }
  }
}
A match still running
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).

Errors

StatusCodeWhen
404not-foundNo 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

PUT/api/v1/matches/{matchId}/shortlist

Replaces 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

NameInTypeRequiredDescription
matchIdPathstring (uuid)RequiredThe match's id: data.id from the answer that started it.
If-MatchHeaderstringOptionalThe 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)
FieldTypeRequiredDescription
homesstring[]RequiredThe 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
Examples
{
  "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

200

The match, with the shortlist as you arranged it.

HeadersETag

Reordered
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).

Errors

StatusCodeWhen
404not-foundNo such match in your workspace.
400invalidA home is named twice, or there are more than twenty; issues names each.
400invalid-jsonThe body is empty or not JSON.
400invalid-if-matchThe If-Match is not a tag a read returned.
413too-largeThe body is over 64 KiB.
409match-not-readyThe match is still running, or stopped or failed: it has no shortlist yet.
412revision-mismatchThe shortlist changed since the tag in If-Match.
422unknown-homeAn 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

POST/api/v1/briefs/{searchId}/matches

Product 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
Idempotency-KeyHeaderstringOptionalA 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)
FieldTypeRequiredDescription
notifyobjectOptionalWho 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.agentobjectOptionalTell me: you, by text and by email.
notify.agent.textbooleanOptionalText 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.emailbooleanOptionalEmail you when it is ready. Left out: as text.
notify.clientbooleanOptionalSend 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.alsostring[]OptionalUp to five more emails or mobile numbers, each sent the share link the same way.at most 5 items
notify.callbackUrlstringOptional1 to 2000 characters
Examples
{
  "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

202

A live run was queued. Read the match until status is not running.

HeadersLocationRetry-AfterETagIdempotent-Replayed

A match, just queued
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).
201

A data set answered at once: the match is complete.

HeadersLocationETagIdempotent-Replayed

A complete match
{
  "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)
FieldTypeDescription
dataobject
data.idstring (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.briefIdstring (uuid)
data.briefVersionintegerThe revision of the brief this match ran.
data.clientIdstring (uuid) | nullThe brief's client, or null for a brief that is nobody's.
data.createdAtstring (date-time)
data.updatedAtstring (date-time)
data.dataAsOfstring (date-time) | nullWhen the listings were read. Null for a data set match.
data.runobject | nullThe live run behind a Homes for sale match; null for a data set match.
data.run.idstring (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" | nullThe play the run is on, or null before it starts and after it ends.
data.run.stepLabelstring | nullThat play in words for a person.
data.run.attemptsintegerHow many times a driver has claimed the run. More than one means it resumed after a crash or a deadline.
data.run.progressobject
data.run.progress.doneintegerPlays finished.
data.run.progress.totalintegerPlays in a run.
data.run.progress.percentintegerHow far along, 0 to 100.0 to 100
data.run.startedAtstring (date-time) | null
data.run.finishedAtstring (date-time) | null
data.run.errorobject | nullWhy a run failed, with the digest to quote to us; null otherwise.
data.run.error.codestring
data.run.error.digeststring | null
data.run.linksobject
data.run.links.selfstring
data.run.links.cancelstringWhere to POST to cancel the run.
data.summarystring | nullA paragraph on how the homes fit, in markdown. Null for a data set match.
data.countsobject | nullNull until the match is complete.
data.counts.shortlistedintegerHomes on the shortlist.
data.counts.removedintegerThe match's own shortlisted homes you took off it.
data.counts.excludedintegerHomes the match graded and left out.
data.counts.consideredintegerHomes the match weighed.
data.shortlistobject[]The homes that fit, in the order you curated, else the match's own order. Empty until the match is complete.
data.shortlist[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.shortlist[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.shortlist[].addressstring | null
data.shortlist[].areastring | nullThe city.
data.shortlist[].statestring | null
data.shortlist[].postalCodestring | null
data.shortlist[].neighbourhoodstring | null
data.shortlist[].pricenumber | null
data.shortlist[].bedsnumber | null
data.shortlist[].bathsnumber | null
data.shortlist[].sqftnumber | null
data.shortlist[].propertyTypestring | null
data.shortlist[].yearBuiltinteger | null
data.shortlist[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.shortlist[].images[].urlstring (uri)
data.shortlist[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.shortlist[].locationobject | null
data.shortlist[].location.latnumber
data.shortlist[].location.lngnumber
data.shortlist[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.shortlist[].listedBy.officestring
data.shortlist[].listedBy.listingKeystring
data.shortlist[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.shortlist[].details.statusstringat least 1 characters
data.shortlist[].details.yearBuiltinteger | null
data.shortlist[].details.lotSqftnumber | nullat least 0
data.shortlist[].details.garageSpacesnumber | nullat least 0
data.shortlist[].details.daysOnMarketinteger | nullat least 0
data.shortlist[].details.remarksstring
data.shortlist[].details.featuresstring[]
data.shortlist[].details.latitudenumber | null-90 to 90
data.shortlist[].details.longitudenumber | null-180 to 180
data.shortlist[].details.sourcestringat least 1 characters
data.shortlist[].details.sourceUrlstring (uri), optional
data.shortlist[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.shortlist[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.shortlist[].scoreParts.textnumber | null0 to 100
data.shortlist[].scoreParts.photosnumber | null0 to 100
data.shortlist[].scoreParts.neighbourhoodnumber | null0 to 100
data.shortlist[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.shortlist[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.shortlist[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.shortlist[].highlightsstring[]
data.shortlist[].concernsstring[]
data.shortlist[].lookAndFeelstring | null
data.shortlist[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.shortlist[].commutes[].labelstring1 to 120 characters
data.shortlist[].commutes[].minutesinteger0 to 240
data.shortlist[].commutes[].estimatedboolean
data.shortlist[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.shortlist[].signals.schoolnumber | null
data.shortlist[].signals.safetynumber | null
data.shortlist[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.shortlist[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.shortlist[].outsidestring[] | nullWhy 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.removedobject[]The match's own shortlisted homes you took off the shortlist, in the match's order.
data.removed[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.removed[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.removed[].addressstring | null
data.removed[].areastring | nullThe city.
data.removed[].statestring | null
data.removed[].postalCodestring | null
data.removed[].neighbourhoodstring | null
data.removed[].pricenumber | null
data.removed[].bedsnumber | null
data.removed[].bathsnumber | null
data.removed[].sqftnumber | null
data.removed[].propertyTypestring | null
data.removed[].yearBuiltinteger | null
data.removed[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.removed[].images[].urlstring (uri)
data.removed[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.removed[].locationobject | null
data.removed[].location.latnumber
data.removed[].location.lngnumber
data.removed[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.removed[].listedBy.officestring
data.removed[].listedBy.listingKeystring
data.removed[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.removed[].details.statusstringat least 1 characters
data.removed[].details.yearBuiltinteger | null
data.removed[].details.lotSqftnumber | nullat least 0
data.removed[].details.garageSpacesnumber | nullat least 0
data.removed[].details.daysOnMarketinteger | nullat least 0
data.removed[].details.remarksstring
data.removed[].details.featuresstring[]
data.removed[].details.latitudenumber | null-90 to 90
data.removed[].details.longitudenumber | null-180 to 180
data.removed[].details.sourcestringat least 1 characters
data.removed[].details.sourceUrlstring (uri), optional
data.removed[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.removed[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.removed[].scoreParts.textnumber | null0 to 100
data.removed[].scoreParts.photosnumber | null0 to 100
data.removed[].scoreParts.neighbourhoodnumber | null0 to 100
data.removed[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.removed[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.removed[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.removed[].highlightsstring[]
data.removed[].concernsstring[]
data.removed[].lookAndFeelstring | null
data.removed[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.removed[].commutes[].labelstring1 to 120 characters
data.removed[].commutes[].minutesinteger0 to 240
data.removed[].commutes[].estimatedboolean
data.removed[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.removed[].signals.schoolnumber | null
data.removed[].signals.safetynumber | null
data.removed[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.removed[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.removed[].outsidestring[] | nullWhy 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.excludedobject[]Homes the match left out, each with why. At most 200 are listed; counts.excluded is the whole number.
data.excluded[].idstringThe 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[].rankinteger | nullIts place on the shortlist, 1 first; null for a home that is not on it.at least 1
data.excluded[].ownRankinteger | nullWhere the match itself put it, whatever the order is now; null for a home the match left out.at least 1
data.excluded[].addressstring | null
data.excluded[].areastring | nullThe city.
data.excluded[].statestring | null
data.excluded[].postalCodestring | null
data.excluded[].neighbourhoodstring | null
data.excluded[].pricenumber | null
data.excluded[].bedsnumber | null
data.excluded[].bathsnumber | null
data.excluded[].sqftnumber | null
data.excluded[].propertyTypestring | null
data.excluded[].yearBuiltinteger | null
data.excluded[].imagesobject[]The hero first, then the rooms worth opening with their labels, then the gallery.
data.excluded[].images[].urlstring (uri)
data.excluded[].images[].captionstring, optionalThe room the photo shows, such as "Kitchen", when the photo is labeled. Absent otherwise: a Homes for sale hero never has one.
data.excluded[].locationobject | null
data.excluded[].location.latnumber
data.excluded[].location.lngnumber
data.excluded[].listedByobject | nullThe listing office, which MLS rules require beside a home; null for a data set home.
data.excluded[].listedBy.officestring
data.excluded[].listedBy.listingKeystring
data.excluded[].detailsobject | nullA data set home's stored details; null for a Homes for sale home.
data.excluded[].details.statusstringat least 1 characters
data.excluded[].details.yearBuiltinteger | null
data.excluded[].details.lotSqftnumber | nullat least 0
data.excluded[].details.garageSpacesnumber | nullat least 0
data.excluded[].details.daysOnMarketinteger | nullat least 0
data.excluded[].details.remarksstring
data.excluded[].details.featuresstring[]
data.excluded[].details.latitudenumber | null-90 to 90
data.excluded[].details.longitudenumber | null-180 to 180
data.excluded[].details.sourcestringat least 1 characters
data.excluded[].details.sourceUrlstring (uri), optional
data.excluded[].scorenumber | nullThe blended score, 0 to 100 for Homes for sale. Null when the match did not score it.
data.excluded[].scorePartsobject | nullThe 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.mathnumber0 to 100
data.excluded[].scoreParts.textnumber | null0 to 100
data.excluded[].scoreParts.photosnumber | null0 to 100
data.excluded[].scoreParts.neighbourhoodnumber | null0 to 100
data.excluded[].reasonsstring[]Why it fits: a data set home's reasons, or a Homes for sale home's pros.
data.excluded[].tradeoffsstring[]What it gives up: a data set home's trade-offs, or a Homes for sale home's cons.
data.excluded[].takestring | nullOne sentence on the home. Null on a data set home, which is not graded.
data.excluded[].highlightsstring[]
data.excluded[].concernsstring[]
data.excluded[].lookAndFeelstring | null
data.excluded[].commutesobject[]Minutes to each place the brief named, and whether they were estimated rather than routed.
data.excluded[].commutes[].labelstring1 to 120 characters
data.excluded[].commutes[].minutesinteger0 to 240
data.excluded[].commutes[].estimatedboolean
data.excluded[].signalsobject | nullWhat the web read of its neighborhood; null when none turned up.
data.excluded[].signals.schoolnumber | null
data.excluded[].signals.safetynumber | null
data.excluded[].missesany[]A near miss's must-haves it misses, on a data set shortlist.
data.excluded[].unconfirmedstring[]The buyer's must-haves this listing never confirms, in their words.
data.excluded[].outsidestring[] | nullWhy 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[].whystring[]Every reason it was left out.
data.excluded[].categorystring | nullThe kind of reason, when the run named one.
data.funnelobject | nullHow many homes each stage kept or dropped, from what the source returned to the shortlist. Null for a data set match.
data.funnel.fetchednumber
data.funnel.terminalStatusnumberdefault 0
data.funnel.noCoordinatesnumberdefault 0
data.funnel.outsideAreanumberdefault 0
data.funnel.duplicatesnumberdefault 0
data.funnel.wrongTypenumberdefault 0
data.funnel.poolednumber
data.funnel.beyondReachnumberdefault 0
data.funnel.scorednumber
data.funnel.gradednumber
data.funnel.shortlistednumber
data.reasonCountsobjectHow many homes each exclusion reason cost.
data.creditsobject[]Attribution a provider's terms require wherever the homes are shown.
data.credits[].textstring
data.credits[].urlstring
data.notesstring[]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.itemsobject[]
data.compliance.items[].idstring
data.compliance.items[].status"pass" | "warn" | "fail" | "info"
data.compliance.items[].detailstring
data.compliance.items[].checkstring
data.compliance.items[].evidenceobject[]default []
data.compliance.items[].evidence[].sourcestring
data.compliance.items[].evidence[].listingKeystring | null
data.compliance.items[].evidence[].excerptstring
data.compliance.reviewedAtstring
data.compliance.source"model" | "stand-in"
data.notifyobject | nullWho hears when it is ready, and where each send stands. Null when nothing was asked.
data.notify.askedobject
data.notify.asked.agentobjectTell me: you, by text and by email.
data.notify.asked.agent.textboolean
data.notify.asked.agent.emailboolean
data.notify.asked.clientbooleanSend the client the share link once the Fair Housing review passes or warns.
data.notify.asked.alsostring[]The other addresses named, masked.
data.notify.recipientsobject[]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[].tostring | nullA 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[].reasonstring | nullWhy 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[].sendAfterstring (date-time) | nullWhen a text waiting out quiet hours goes.
data.linksobject
data.links.selfstring
data.links.briefstringThe brief it ran.
data.links.shortliststringWhere to PUT the ordered list.
data.links.sharesstringWhere to POST a share and GET the match's shares.
data.links.pdfstringThe match as a PDF (needs search:read).

Errors

StatusCodeWhen
400invalidThe 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.
400invalid-jsonThe body is not JSON.
400invalid-idempotency-keyThe Idempotency-Key is malformed.
402out-of-creditsThe org has no matches left this month.
402person-limit-reachedThe person the key acts as has used their own monthly matches.
404not-foundNo such brief in your workspace.
409idempotency-key-reusedThe Idempotency-Key was used for a different brief.
422brief-unrunnableThe 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.
429rate-limitedThe hourly cap on starting matches is spent (the answer has no RateLimit header).
429too-many-active3 runs are already queued or running.
503search-unavailableAn outside service the match needs is not configured here.
503studio-incompleteA prompt the match engine runs is incomplete in Livia's AI settings; issues names the step. Nothing was started or spent.
400invalidThe body is not { notify: { callbackUrl } }, or the URL is not one a callback may use; issues names it.
400invalid-jsonThe body is not JSON.
413too-largeThe body is over its limit.
422callback-url-refusednotify.callbackUrl is plain http to localhost on a deployment that is not development.
422callback-needs-keynotify.callbackUrl was named by a signed-in session rather than an API key.
422no-signing-secretnotify.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

GET/api/v1/briefs/{searchId}/matches

The 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

NameInTypeRequiredDescription
searchIdPathstring (uuid)RequiredThe search's id.
limitQueryintegerOptionalHow many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored.
cursorQuerystringOptionalWhere 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

200

One page of matches.

One match
{
  "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)
FieldTypeDescription
dataobject[]
data[].idstring (uuid)
data[].kind"dataset" | "market"
data[].status"complete" | "failed" | "running" | "canceled"
data[].briefIdstring (uuid)
data[].briefVersioninteger
data[].homesinteger | nullThe shortlist's size; null until the match is complete.
data[].createdAtstring (date-time)
data[].updatedAtstring (date-time)
data[].linksobject
data[].links.selfstring
linksobject
links.nextstring | nullThe URL of the next page, or null when this is the last. Follow it as given.

Errors

StatusCodeWhen
404not-foundNo such brief in your workspace.
400invalid-cursorThe 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