# Value a property with comparables

> **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).

`POST https://platform.casafari.com/v1/comparables/search`

[Comparables & Valuation](/docs/comparables-valuation) · [REST API](/docs/rest/comparables-valuation). Send `Authorization: Bearer $CASAFARI_API_KEY`: a platform API key (`cf_sk_...`) from [the console](https://platform.casafari.com/console), or an OAuth access token; `X-API-Key` carries the key too. See [platform API keys](/docs/rest#platform-api-keys). Costs 25 tokens a call (1 token = EUR 0.04).

Over MCP: [`comparables_get_comparables`](/docs/comparables-valuation/get-comparables) (equivalent). See [MCP and REST compared](/docs/parity#comparables-valuation).

## Description

Costs 25 tokens a call. Page size: `comparables_count` in the body, at most 50 (a Free plan account is capped lower).

## Request body

Content type `application/json`. Required. Type: `object`.

- `comparables_count` (integer, required): Maximum number of comparable properties in results. 1–50.
- `location_boundary` (object, required): Location to search within. Can be defined as a polygon of geo-points or a circle with a given target point and a distance. Only one value should be provided.
  - `polygon` (object[], optional): Closed polygon of geo-points to search within. First and last points must match. at least 4 items.
    - `latitude` (number, required): Latitude. -90–90.
    - `longitude` (number, required): Longitude. -180–180.
  - `circle` (object, optional): Circle boundary to search within.
    - `distance` (number, optional): Circle radius in kilometres (not metres) from `target_point`: 0.05 to 50, default 5. 0.05–50; default 5.
    - `target_point` (object, required): Target point to search around. Can be defined as coordinates, address or cadastral reference of the property. Only one value should be provided.
      - `coordinates` (object, optional): Target point coordinates to search around.
        - `latitude` (number, required): Latitude. -90–90.
        - `longitude` (number, required): Longitude. -180–180.
      - `address` (string, optional): Address of the property to define the point to search around.
      - `cadastral_reference` (object, optional): Cadastral reference of the property to define the point to search around. For now available only for Spain.
        - `country_code` (string, required): Country code following the ISO 3166-1 alpha-2 rules. Values: `ES`.
        - `cadastral_reference` (string, required): Cadastral reference of the estate.
        - `province` (string, optional): Name of the estate's province.
        - `municipality` (string, optional): Name of the estate's municipality.
- `sold_or_rented_after` (string, optional, nullable): Properties sold/rented since this date (in the format `YYYY-MM-DD`) will be considered as possible comparables. Default value: 9 months ago, counting from today. If `null` is passed, only active properties will be considered.
- `operation` (string, required): Operation type. Values: `sale`, `rent`.
- `comparables_types` (string[], required): Property types to compare with, all from one type group. Groups: apartment (erdgeschosswohnung, etagenwohnung, dachgeschosswohnung, duplex, studio, penthouse, apartment); house (villa, reihenhaus, palace, country_estate, zweifamilienhaus, reihenmittelhaus, reihenendhaus, landwirtschaftliche_betriebe, country_house, townhouse, chalet, bungalow, einfamilienhaus, house; family_house is deprecated); room (room); building (mix_use_building, office_building, apartment_building); investment (restaurant, other_commercial, warehouse, office, industrial, werkstatt, hotel, retail); plot (rural_plot, urban_plot; plot is deprecated); other (garage, other, parking). Not every type is available in every country. Values: `apartment`, `studio`, `duplex`, `penthouse`, `dachgeschosswohnung`, `etagenwohnung`, `erdgeschosswohnung`, `country_house`, `house`, `palace`, `townhouse`, `villa`, `country_estate`, `chalet`, `bungalow`, `family_house`, `reihenhaus`, `reihenendhaus`, `reihenmittelhaus`, `einfamilienhaus`, `zweifamilienhaus`, `landwirtschaftliche_betriebe`, `retail`, `office`, `industrial`, `warehouse`, `hotel`, `other_commercial`, `restaurant`, `werkstatt`, `plot`, `urban_plot`, `rural_plot`, `room`, `other`, `garage`, `parking`, `apartment_building`, `office_building`, `mix_use_building`.
- `min_price` (integer, optional): The minimum price filter for comparables result. Default value: 0. 0–2147483647.
- `max_price` (integer, optional): The maximum price filter for comparables result. 1–2147483647.
- `condition` (string, optional): Property condition: used, ruin, very-good, new or other. Values: `used`, `ruin`, `very-good`, `new`, `other`.
- `bedrooms` (integer, optional): Target number of bedrooms of the property being valued. A similarity target, not a filter: comparables with other bedroom counts can be returned, ranked lower. Cannot be used together with `rooms`. 0–15000.
- `rooms` (integer, optional): Number of rooms (cannot be used together with `bedrooms`). 0–15000.
- `bathrooms` (integer, optional): Number of bathrooms. 1–15000.
- `construction_year` (integer, optional): Desired construction year. 1–3000.
- `total_area` (integer, optional): Desired total area, square meters. This field is required for `hotel`, `industrial`, `office`, `other_commercial`, `restaurant`, `retail`, `warehouse`, `werkstatt` property types if `target_point.cadastral_reference` is not provided. 5–10000000.
- `plot_area` (integer, optional): Desired plot area, square meters. This field is required for `rural_plot` and `urban_plot` property types if `target_point.cadastral_reference` is not provided. 20–10000000.
- `floors` (string[], optional): List of floor types. Values: `no_floor`, `ground`, `middle`, `top`.
- `floor_number` (integer[], optional): Desired list of floor numbers. Negative values indicate underground floors (e.g. basements). Minimum value is -250. Maximum value is 250. -250–250.
- `orientation` (string, optional): Property view orientation. Values: `exterior`, `interior`.
- `views` (string[], optional): List of views from the property. Values: `water`, `landscape`, `city`, `golf`, `park`.
- `directions` (string[], optional): List of cardinal directions the property faces. Values: `north`, `south`, `east`, `west`.
- `characteristics` (object, optional): Property characteristics.
  - `must_have` (string[], optional): Include only properties that have all these characteristics. Values: `balcony`, `elevator`, `no_elevator`, `garage`, `garden`, `parking`, `storage`, `swimming_pool`, `terrace`, `rental_license`, `furniture`, `rented_out`, `life_annuity`.
  - `nice_to_have` (string[], optional): Include properties that have any of these characteristics. Values: `balcony`, `elevator`, `no_elevator`, `garage`, `garden`, `parking`, `storage`, `swimming_pool`, `terrace`, `rental_license`, `furniture`, `rented_out`, `life_annuity`.
  - `exclude` (string[], optional): Exclude properties that contain any of these characteristics. Values: `balcony`, `elevator`, `no_elevator`, `garage`, `garden`, `parking`, `storage`, `swimming_pool`, `terrace`, `rental_license`, `furniture`, `rented_out`, `life_annuity`.
- `energy_ratings` (string[], optional): List of energy ratings. Values: `Unknown`, `A+`, `A`, `B`, `C`, `D`, `E`, `F`, `G`, `H`.
- `days_on_market_from` (integer, optional): Minimum days on market value. 1–10000.
- `days_on_market_to` (integer, optional): Maximum days on market value. 1–10000.
- `with_agencies` (string[], optional): Only properties advertised by these agencies, companies or sources, as free-text names. No list of names is available over MCP; an unknown name matches nothing.
- `without_agencies` (string[], optional): Exclude properties advertised by these agencies, companies or sources, as free-text names. No list of names is available over MCP.
- `exclude_outliers` (boolean, optional): Exclude properties that are significantly underpriced or overpriced compared to similar properties. Default value: true.

## Example request

Placeholders only: replace the token and the values with your own.

```bash
curl -X POST "https://platform.casafari.com/v1/comparables/search" \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "operation": "sale",
  "comparables_types": [
    "apartment"
  ],
  "bedrooms": 3,
  "total_area": 95,
  "comparables_count": 5,
  "location_boundary": {
    "circle": {
      "target_point": {
        "address": "Calle de Serrano 50, Madrid, Spain"
      },
      "distance": 1
    }
  }
}'
```

## Responses

### 200 Success.

Type: `object`.

### Errors

Every error is an `application/problem+json` body (RFC 9457) with `type` (a page that explains it), `title`, `status`, `detail` (what to do), `instance`, `code` and `request_id` (what to quote to support). A `402` carries an `upgrade_url`, a `429` a `Retry-After` header. The codes each status can carry:

- `400`: `invalid_request`, `key_in_query`, `page_depth_exceeded` (https://platform.casafari.com/errors/invalid-request, https://platform.casafari.com/errors/key-in-query, https://platform.casafari.com/errors/page-depth-exceeded)
- `401`: `unauthorized`, `invalid_credential`, `credential_revoked`, `token_expired` (https://platform.casafari.com/errors/unauthorized, https://platform.casafari.com/errors/invalid-credential, https://platform.casafari.com/errors/credential-revoked, https://platform.casafari.com/errors/token-expired)
- `402`: `payment_required` (https://platform.casafari.com/errors/payment-required)
- `403`: `insufficient_scope`, `not_entitled`, `account_suspended` (https://platform.casafari.com/errors/insufficient-scope, https://platform.casafari.com/errors/not-entitled, https://platform.casafari.com/errors/account-suspended)
- `404`: `not_found` (https://platform.casafari.com/errors/not-found)
- `405`: `method_not_allowed` (https://platform.casafari.com/errors/method-not-allowed)
- `409`: `conflict` (https://platform.casafari.com/errors/conflict)
- `413`: `payload_too_large` (https://platform.casafari.com/errors/payload-too-large)
- `415`: `unsupported_media_type` (https://platform.casafari.com/errors/unsupported-media-type)
- `422`: `validation_failed` (https://platform.casafari.com/errors/validation-failed)
- `429`: `rate_limited`, `daily_limit_reached`, `request_limit_reached`, `usage_limit_reached` (https://platform.casafari.com/errors/rate-limited, https://platform.casafari.com/errors/daily-limit-reached, https://platform.casafari.com/errors/request-limit-reached, https://platform.casafari.com/errors/usage-limit-reached)
- `500`: `internal_error` (https://platform.casafari.com/errors/internal-error)
- `502`: `upstream_error` (https://platform.casafari.com/errors/upstream-error)
- `503`: `capacity_exhausted`, `unavailable` (https://platform.casafari.com/errors/capacity-exhausted, https://platform.casafari.com/errors/unavailable)
- `504`: `upstream_timeout` (https://platform.casafari.com/errors/upstream-timeout)

## Related pages

- [Search comparables (v1) (POST /api/v1/comparables/search)](/docs/rest/comparables-valuation/search-comparables-v1)
- [Initialize an AI Builder session (v2) (POST /api/v2/comparables/ai-builder)](/docs/rest/comparables-valuation/initialize-an-ai-builder-session-v2)
- [Search comparables (v2) (POST /api/v2/comparables/search)](/docs/rest/comparables-valuation/search-comparables-v2)
- [Search estimated prices (v1) (POST /api/v1/valuation/comparables-prices)](/docs/rest/comparables-valuation/search-estimated-prices-v1)
- [Comparables & Valuation REST API: all operations](/docs/rest/comparables-valuation)
- [How to get a bearer token for the Casafari REST API](/docs/rest)
- [MCP vs REST API compared](/docs/parity)
