Listing search
Search published Matchai listings in natural language with the /ask endpoint (NLWeb). Parameters, response shape, host-aware scope, limits and examples.
/ask searches published listings from a plain sentence such as "3 bedroom condo in Laval under 600k". It follows the NLWeb protocol, so NLWeb clients can call it without custom code. It is public and read-only, and it needs no account or API key.
https://matchai.co/askIt returns listings in the order a person would want them: best match first, by relevance to the request and by how recently the listing was updated. No broker can pay to change the order or to be included.
Search in one request
curl "https://matchai.co/ask?query=3+bedroom+condo+in+Laval+under+600k"An abridged answer. This search matched one listing, and the score is an example value:
{
"_meta": { "response_type": "answer", "version": "0.55", "mode": "list" },
"query_id": "6f1d2c1e-3b0a-4a54-9f2e-0c7b8a5d9e41",
"site": "matchai.co",
"mode": "list",
"query": "3 bedroom condo in Laval under 600k",
"results": [
{
"url": "https://alice.matchai.co/bright-condo-montmorency",
"name": "Bright 3-bedroom condo near Montmorency metro",
"site": "alice.matchai.co",
"score": 0.872,
"description": "$585,000, condo for sale · 3 bedrooms · 1.5 bathrooms · 1,120 sq ft · Montmorency, Laval, Québec · Listed by Alice Tremblay (Agence Exemple)",
"schema_object": {
"@context": "https://schema.org",
"@type": "RealEstateListing",
"url": "https://alice.matchai.co/bright-condo-montmorency",
"name": "Bright 3-bedroom condo near Montmorency metro",
"image": "https://media.example.com/listings/bright-condo-montmorency/cover.jpg",
"dateModified": "2026-10-12T14:03:22.000Z",
"offers": {
"@type": "Offer",
"price": 585000,
"priceCurrency": "CAD",
"availability": "https://schema.org/InStock",
"businessFunction": "http://purl.org/goodrelations/v1#Sell",
"url": "https://alice.matchai.co/bright-condo-montmorency",
"offeredBy": {
"@type": "RealEstateAgent",
"name": "Alice Tremblay",
"worksFor": { "@type": "Organization", "name": "Agence Exemple" }
}
},
"about": {
"@type": "Apartment",
"numberOfBedrooms": 3,
"numberOfBathroomsTotal": 1.5,
"floorSize": { "@type": "QuantitativeValue", "value": 1120, "unitCode": "FTK" },
"address": { "@type": "PostalAddress", "addressLocality": "Laval", "addressRegion": "Québec" }
}
}
}
]
}The names, addresses and photo host in these examples are made up.
Request
Send the search as a GET with query-string parameters, or as a POST with a JSON body.
GET
Field
Type
POST
Send Content-Type: application/json. The body can be up to 16 KB.
{ "query": "4½ à louer sur le Plateau" }The query can also be an object, as in NLWeb:
{ "query": { "text": "condo near the metro in Montréal" }, "prefer": { "mode": "list" } }Field
Type
Query-string parameters fill in anything the body leaves out.
What the query understands
The search reads your sentence with a small, predictable parser. It does not call a language model, so the same sentence always gives the same filters. It understands English, French and Spanish.
| You write | It filters on |
|---|---|
under 600k, max 750,000, moins de 750 000 $, hasta 400k | A maximum price |
over 300k, at least 1.2M, plus de 500k, desde 200k | A minimum price |
between 400k and 600k, entre 400k et 600k | A price range |
3 bedroom, 3 br, 3 chambres, 3 habitaciones | At least that many bedrooms |
4½, 5½ | Québec room counts. A 4½ has two bedrooms, so N½ means at least N − 2 bedrooms. |
2 baths, 1.5 bathrooms, 2 sdb | At least that many bathrooms |
for sale, à vendre, en venta | Properties for sale |
for rent, à louer, en alquiler | Rentals |
condo, duplex, maison, chalet, terrain, townhouse, commercial | A property type: house, condo, apartment, townhouse, plex, land, cottage or commercial |
Amounts can be written as 600k, 1.2M, 600 000, $750,000 or 2 million. A small bare number with no unit and no dollar sign, such as over 2, is not read as a price. If the sentence asks for both sale and rent, or for neither, the search does not filter on it.
Everything else becomes a keyword. The search keeps up to 6 keywords, drops words shorter than 3 letters and common filler words, and ignores accents, so montreal finds Montréal. Keywords are matched against the title, the place names, the property type and the description. A match in a place name counts most, then the title, then the property type, then the description.
Searches return listings that are available now. Sold and rented listings are not returned.
Response
Field
Type
Each item in results:
Field
Type
A successful answer carries Link: </llms.txt>; rel="describedby", </openapi.json>; rel="service-desc". For photos, highlights and the full description of one listing, use the MCP server's tools or read the listing's Markdown copy.
Which listings are searched
/ask answers for the host you call, so asking a broker's own site searches that broker, and asking matchai.co searches everyone.
| You call | It searches |
|---|---|
https://matchai.co/ask | Every published listing on Matchai. Add site to limit it to one broker. |
https://{name}.matchai.co/ask, a Matchai Site | The listings published on that broker's site only. |
https://{domain}/ask, a broker's own domain | The same, for the site that domain serves. |
https://{name}.matchai.pro/ask, a Matchai Page | The request is redirected to https://matchai.co/ask, so it searches every broker. |
Notes:
- On a Matchai Site or a broker's own domain,
siteis ignored: the host decides the scope. - On
matchai.co,sitetakes a broker's site host. A value that matches no published site is ignored, and the search covers everyone. It does not return an empty list. - A Matchai Page has no search of its own. The redirect is a
307, which keeps the method and the body. To search one professional's listings, ask their Matchai Site, or callmatchai.cowith their site assite. From browser code, callmatchai.co/askdirectly, because a browser cannot follow a redirect on a cross-origin preflight. - A host with no published site answers
404.
Limits, caching and CORS
- Rate limit: 60 requests per minute for each calling address, across
GETandPOST. Above it, the answer is429withRetry-After: 60. - Results: at most 10 per request. There is no paging, so narrow the sentence to reach other listings.
- Caching: a
GETwithout aquery_idcan be cached for up to a minute (Cache-Control: public, max-age=60). Everything else is sent withno-store. A new listing appears in results within about a minute. - CORS: open to every origin for
GET,POSTandOPTIONS, so browser code can call it.OPTIONSanswers204, and preflight answers can be cached for 24 hours.
Errors
Errors are JSON with a stable error code and a message you can show to a person.
{ "error": "rate_limited", "message": "Too many requests. Try again in a minute." }| Status | error | Meaning and what to do |
|---|---|---|
400 | missing_query | There is no search sentence. Send ?query= or a JSON body with query. |
400 | invalid_json | The POST body is not valid JSON. |
413 | too_large | The POST body is over 16 KB. Send a shorter sentence. |
404 | not_found | The host you called has no published listings to search. |
429 | rate_limited | Too many requests. Wait for the Retry-After seconds. |
503 | unavailable | Search is temporarily unavailable. Retry after the Retry-After seconds. |
An empty results array is a successful answer: nothing published matched. Try a wider area, a higher budget or fewer requirements.
More examples
Search one broker's listings by calling their site. Replace alice with a real site name:
curl "https://alice.matchai.co/ask?query=condo+under+500k"Limit a search on matchai.co to one broker:
curl "https://matchai.co/ask?query=house+for+sale&site=alice.matchai.co"Search from code with a POST:
curl -X POST https://matchai.co/ask \
-H "Content-Type: application/json" \
-d '{ "query": "4½ à louer sur le Plateau", "query_id": "rent-plateau-1" }'