# What does a 2-bedroom apartment cost in this area, and how are prices spread?

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

Casafari Area Insights answers both questions over MCP. `ma_get_bedrooms_distribution` returns `properties_count`, `average_price` and `average_price_per_sqm` for each bedroom count in an area, so you read the 2-bedroom row directly. `ma_get_price_distribution` returns the number of properties in each price interval, with `is_mean` marking the band that holds the mean price.

Products: [Area Insights](/docs/area-insights).

## Short answer

Two Area Insights tools answer this question.

`ma_get_bedrooms_distribution` returns one row per bedroom count, with:

- `bedrooms` (a label).
- `properties_count`.
- `average_price`.
- `average_price_per_sqm`.

`ma_get_price_distribution` returns one row per price interval, with:

- `lower_bound` and `upper_bound`.
- `properties_count`.
- `is_mean`, which is `true` for the band that holds the mean price.

Together they give the going price for each bedroom count and show where supply sits across price bands.

## Steps

### Resolve the area

1. Call `ma_get_location_typeahead` with an English place name, for example `Malaga`, and keep the `location_id`. Use the `breadcrumbs` to make sure it is the city you mean.

### Call ma_get_bedrooms_distribution with type_group, business_type, bedrooms_range (0 to 10)

2. Call `ma_get_bedrooms_distribution` with a `request_data` object.
   - Required: `type_group` (`apartment` or `house`), `business_type` (`sale` or `rent`) and `custom_location_boundary`.
   - Optional: `bedrooms_range` (`min` and `max` from 0 to 10), plus `price_range`, `total_area_range`, `conditions` and `exclude_outliers` (default `true`).

### Call ma_get_price_distribution with the same boundary and an optional price_range

3. Call `ma_get_price_distribution` with the same `type_group`, `business_type` and `custom_location_boundary`. Add a `price_range` to focus on one window, for example 200,000 to 300,000.

### Over REST, POST /market-analytics-api/distributions/properties for the properties distribution

4. Over REST, send `POST /market-analytics-api/distributions/properties`. Its body takes:
   - `types`, `business_type` and `custom_location_boundary`.
   - Range filters (`price_range`, `price_per_sqm_range`, `rooms_range`, `bedrooms_range`, `bathrooms_range`, `total_area_range`, `plot_area_range`, `construction_year_range`).
   - `characteristics`, `conditions`, `private`, `bank`, `auction` and `exclude_outliers`.

   Its response fields are documented on the [operation page](/docs/rest/area-insights/properties-distribution).

## Example: apartments for sale in Málaga

Prompt to the assistant: *"What does a 2-bedroom apartment for sale in Málaga cost, and how many apartments are priced between 200,000 and 300,000?"*

The assistant calls `ma_get_location_typeahead` (`Malaga`), then `ma_get_bedrooms_distribution`:

```json
{
  "request_data": {
    "type_group": "apartment",
    "business_type": "sale",
    "custom_location_boundary": {"location_ids": [MALAGA_LOCATION_ID]},
    "bedrooms_range": {"min": 1, "max": 4}
  }
}
```

Then it calls `ma_get_price_distribution`:

```json
{
  "request_data": {
    "type_group": "apartment",
    "business_type": "sale",
    "custom_location_boundary": {"location_ids": [MALAGA_LOCATION_ID]},
    "price_range": {"min": 200000, "max": 300000}
  }
}
```

For the cost question, it reads the row where `bedrooms` is `2`: `average_price` and `average_price_per_sqm`, with `properties_count` as the sample size. For the count question, it sums `properties_count` across the returned bands and notes which band has `is_mean` set. The figures come from the live calls; these docs publish none.

## How to read the result

### Bedroom rows for segmentation and unit mix

Use the bedroom rows in two ways:

- **Pricing:** compare a property's asking price per m² with `average_price_per_sqm` for its bedroom count.
- **Supply mix:** `properties_count` by bedroom count shows the mix of stock on offer. Developers can compare that mix with the units they plan.

### Price bands: where supply concentrates and where the mean sits

The bands with the highest `properties_count` are where competition for buyers is strongest. The band with `is_mean` `true` holds the mean price. A property priced far above it competes with less, and usually different, stock. An `upper_bound` of null marks the open top band.

## Limits

Availability:

- Both MCP tools are available to Casafari clients with MCP access, using their Casafari account.
- Self-serve access for new users is coming soon.
- `POST /market-analytics-api/distributions/properties` is REST only, for Casafari client accounts.

Coverage:

- The tool descriptions name no specific market.
- Only the `apartment` and `house` type groups are accepted.

Pricing and quotas:

- The sources give no figures for pricing or quotas. Ask [Casafari](https://www.casafari.com/).

### bedrooms_range in the bedrooms distribution is capped at 10

In `ma_get_bedrooms_distribution`, `bedrooms_range.min` and `bedrooms_range.max` accept 0 to 10. Other Area Insights tools accept higher values.

### Boundaries are location ids (up to 10) or a circle

`custom_location_boundary` takes either `location_ids` (1 to 10) or a `circle`. A circle has a `target_point` and a `distance` of 50 to 50,000 metres. Polygons are not accepted by these MCP tools. See [location ids](/docs/faq/location-ids).

## Questions

### Can I get the distribution for rentals?

Yes. Set `business_type` to `rent` in `ma_get_bedrooms_distribution` or `ma_get_price_distribution`. The bedroom rows then show `average_price` and `average_price_per_sqm` as asking rents, and the price bands group properties by rent level. Each request covers either sale or rent, so compare the two markets with two requests that use identical boundaries and filters.

### Can I limit to new or very-good condition properties?

Yes. Both tools accept `conditions`, a list with at least one value from `used`, `ruin`, `very-good`, `new` and `other`, as returned by `GET /api/v1/references/conditions`. For example, `["new", "very-good"]` keeps only properties in those conditions. Condition is a property attribute; it is not a new-development flag.

### Can I use a polygon as the boundary?

Not with the Area Insights MCP tools. Their `custom_location_boundary` takes up to 10 location ids or a circle of 50 to 50,000 metres. The REST distribution operations also take a `custom_location_boundary`, and its accepted shapes are on each operation page. If you need comparables inside an exact polygon, `comps_get-comparables` accepts a closed polygon of at least 4 points.

### How do I compare two cities?

Send one request per city, with identical `type_group`, `business_type` and filters, and change only `custom_location_boundary`. Putting both cities' ids in one `location_ids` list would return a single combined distribution. Then compare the bedroom rows, for example `average_price_per_sqm` for 2 bedrooms, and the position of the `is_mean` band in each city.

All use cases: [Use cases](/docs/use-cases#area-insights).
