# Keyword search from a simple form, no model

> **Casafari is the AI agent-native real estate data intelligence platform.** The most complete property index in Europe: a deduplicated, cleaned property graph of residential and commercial property, for sale and for rent, in 16 countries. Every property is one record with its full price and market history. [How the property graph is built](/docs/property-graph).

**For developers at vendors who need reproducible filters with an audit trail.** Send criteria.keywords and exclude_keywords with no brief and check false: reproducible results with the matched sentence as evidence.

> How do I build a deterministic premises filter from a form with no model in the loop?

## What is the problem?

A simple form (operation, city, a few checkboxes for Spanish phrases) must give the same results every time, with the sentence that triggered each match, and no model in the loop.

## How does it work, step by step?

1. Map each checkbox to a keyword group: synonyms and the Catalan form in one group (`["salida de humos", "sortida de fums"]`), each requirement in its own group. A premises meets a group when its text holds any phrase; write phrases as Spanish agencies do.
2. Map exclusions to `exclude_keywords`.
3. Call `POST /v1/claro/search` ([REST](https://developers.casafari.com/docs/rest/claro/search-premises)) or [search_premises](https://developers.casafari.com/docs/claro/search_premises) with `criteria.keywords`, `exclude_keywords` and any data criteria (`operation`, `cities`, `area_min`, `rent_price_max`), no `brief`, and `"check": false`.
4. Show each met group's `evidence` (the sentence that matched) and `matched` (the phrase it holds) beside the result, with the `excerpt` and the agency's page from `agency_links`.
5. Page with `cursor` and `limit` up to 200 ([paging](https://developers.casafari.com/docs/claro/faq#paging)).

```bash
curl -X POST https://platform.casafari.com/v1/claro/search \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"criteria": {"operation": "rent", "cities": ["madrid"], "keywords": [["salida de humos", "sortida de fums"], ["esquina", "chaflán"]], "exclude_keywords": ["se traspasa"]}, "check": false}'
```

## What do you get?

Exact counts, the criteria as understood, and results in which each keyword group met carries `evidence` and `matched`. Hard criteria (operation, cities, types, price, area) exclude; `exclude_keywords` leaves out a premises whose text holds any of its phrases. The audit trail is in the response, so store it with the result.

## What are the limits?

Matching is on the advertisement text, so a feature an agency did not write down is not found. Per-account limits on calls a minute and a day apply (429 `rate_limited` or `quota_reached`), behind the platform's own limits ([limits](https://developers.casafari.com/docs/limits)). Show excerpts and matched sentences, never the full description ([content terms](https://developers.casafari.com/docs/claro/faq#content-terms)).

## Related use cases

- [Score every premises with your own agent](https://developers.casafari.com/docs/claro/use-cases/score-premises-with-your-own-agent)
- [Load every match into a CRM or warehouse nightly](https://developers.casafari.com/docs/claro/use-cases/nightly-pipeline-into-crm-or-bi)
- [Get location figures for any point in Spain](https://developers.casafari.com/docs/claro/use-cases/explain-any-point-in-spain)
- [Compare a shortlist for the committee dossier](https://developers.casafari.com/docs/claro/use-cases/compare-a-shortlist-for-a-dossier)
- [Claro AI FAQ](https://developers.casafari.com/docs/claro/faq)
