Platform
Get started

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.The most complete property index in Europe: a deduplicated, cleaned property graph.

How the graph is built

AgencyGraph REST API

Base URL https://platform.casafari.com/v1/agencygraph; the country is in the path (/v1/agencygraph/es/..., /v1/agencygraph/pt/...). Send Authorization: Bearer $CASAFARI_API_KEY: a platform API key or an OAuth access token (platform API keys). Each call costs tokens (1 token = EUR 0.04); lists return pages of up to 25 rows (size, offset; the answer's next_offset is the next page's offset, or null after the last), and each page is a call. Only a 2xx answer is billed. Location ids come from Location Lookup (GET /v1/locations/search, free). The MCP tools give the same JSON.

Errors are problem+json with a request_id: 400 invalid_request (malformed input, a country that is not available yet, more than 25 agency_ids, a city dataset bought at another tier than the town's), 400 page_depth_exceeded (past the benchmark's first 100 agencies), 401, 402 (out of tokens), 403 not_entitled, 404 not_found (an unknown agency, town, network or dataset), 502 upstream_error; none of them is billed.

Every example is illustrative: made-up agencies, ids and figures, not real data.

OperationWhat it doesTokensMCP tool
GET /v1/agencygraph/coverageCountries answered and their latest weekly buildFreeagencygraph_coverage
GET /v1/agencygraph/{country}/coverageOne country's towns and agencies in detail5 tokens per callagencygraph_country_coverage
GET /v1/agencygraph/{country}/agenciesFind an agency by name, trading name or websiteFreeagencygraph_resolve_agency
GET /v1/agencygraph/{country}/agencies/{agency_id}One agency: towns, five measures, quarters50 tokens per callagencygraph_agency_profile
GET /v1/agencygraph/{country}/benchmarkAgencies of a town with the five measures75 tokens per page of up to 25 rows (the first 100 agencies of a town)agencygraph_area_benchmark
GET /v1/agencygraph/{country}/market-shareAgencies' shares of a town's stock and flow50 tokens per page of up to 25 rowsagencygraph_market_share
GET /v1/agencygraph/{country}/agencies/{agency_id}/territoryThe towns where an agency works50 tokens per page of up to 25 rowsagencygraph_territory
GET /v1/agencygraph/{country}/networks/{brand}A franchise network and its offices75 tokens per page of up to 25 rowsagencygraph_network
POST /v1/agencygraph/{country}/screenScreen agencies by ranges of the measures100 tokens per page of up to 25 rowsagencygraph_screen_agencies
GET /v1/agencygraph/{country}/changesWhat changed for up to 25 agencies since a date25 tokens per call (up to 25 agencies)agencygraph_changes
GET /v1/agencygraph/{country}/datasetsA town's city dataset tier and priceFreeREST only
POST /v1/agencygraph/{country}/datasets/smallBuy the city dataset of a small city or district2,500 tokens per callREST only
POST /v1/agencygraph/{country}/datasets/midBuy the city dataset of a mid-size city6,250 tokens per callREST only
POST /v1/agencygraph/{country}/datasets/largeBuy the city dataset of a large city12,500 tokens per callREST only
GET /v1/agencygraph/{country}/datasets/{dataset_id}Download a bought city dataset (JSON or CSV)FreeREST only

Countries answered and their latest weekly build

GET /v1/agencygraph/coverage · Free · over MCP: agencygraph_coverage

Lists the countries AgencyGraph answers for, with the date of each country's latest weekly build and the property type groups it measures, and the countries not yet available.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/coverage" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "countries": [
    {
      "country": "ES",
      "name": "Spain",
      "as_of": "2026-10-26",
      "type_groups": [
        "all",
        "apartment",
        "house"
      ],
      "operations": [
        "sale"
      ]
    },
    {
      "country": "PT",
      "name": "Portugal",
      "as_of": "2026-10-26",
      "type_groups": [
        "all",
        "apartment",
        "house"
      ],
      "operations": [
        "sale"
      ]
    }
  ],
  "not_yet_available": [
    {
      "country": "IT",
      "name": "Italy"
    },
    {
      "country": "DE",
      "name": "Germany"
    }
  ],
  "method_url": "https://developers.casafari.com/docs/agencygraph"
}

One country's towns and agencies in detail

GET /v1/agencygraph/{country}/coverage · 5 tokens per call · over MCP: agencygraph_country_coverage

One country's latest weekly build in detail: the towns and agencies measured, their properties, and the 25 towns with the most agencies, each with the size tier of its city dataset.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/coverage" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "name": "Portugal",
  "type_groups": [
    "all",
    "apartment",
    "house"
  ],
  "operations": [
    "sale"
  ],
  "totals": {
    "towns": 300,
    "agencies": 9000,
    "properties": 150000
  },
  "towns": [
    {
      "location_id": 101,
      "name": "Lisboa",
      "agencies": 2100,
      "properties": 26000,
      "dataset_tier": "large"
    },
    {
      "location_id": 102,
      "name": "Cascais",
      "agencies": 650,
      "properties": 7400,
      "dataset_tier": "mid"
    }
  ]
}

Find an agency by name, trading name or website

GET /v1/agencygraph/{country}/agencies · Free · over MCP: agencygraph_resolve_agency

Turns an agency's name, one of its trading names or its website into ranked candidates in one country: agency_id, name, kind (agency, office of a network, network), network, its properties and main towns, and how it matched. Ambiguous names return several candidates and say so. Use the agency_id in the other tools.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • q (string, required): Query parameter. An agency's name, one of its trading names, or its website (domain). 2–100 characters.
  • location_id (integer, optional): Query parameter. Optional: only agencies active in this town: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/agencies?q=Sample%20Homes" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "query": "Sample Homes",
  "ambiguous": true,
  "results": [
    {
      "agency_id": "agc_EXAMPLEHOMES00000000000000",
      "name": "Sample Homes Lisboa",
      "kind": "agency",
      "network": null,
      "matched_by": "name_contains",
      "properties": 214,
      "main_towns": [
        {
          "location_id": 101,
          "name": "Lisboa",
          "properties": 180
        },
        {
          "location_id": 102,
          "name": "Cascais",
          "properties": 34
        }
      ]
    },
    {
      "agency_id": "agc_EXAMPLEPORTO00000000000000",
      "name": "Sample Homes Porto",
      "kind": "office",
      "network": "Example Network",
      "matched_by": "name_contains",
      "properties": 95,
      "main_towns": [
        {
          "location_id": 103,
          "name": "Porto",
          "properties": 95
        }
      ]
    }
  ]
}

One agency: towns, five measures, quarters

GET /v1/agencygraph/{country}/agencies/{agency_id} · 50 tokens per call · over MCP: agencygraph_agency_profile

A merged agency_id answers 200 with the agency it now belongs to and merged_from naming the id you sent.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • agency_id (string, required): Path parameter.
  • operation (string, optional): Query parameter. sale (default): homes for sale. Rentals are not measured yet. Values: sale. default "sale".

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/agencies/agc_EXAMPLEHOMES00000000000000" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "agency": {
    "agency_id": "agc_EXAMPLEHOMES00000000000000",
    "name": "Sample Homes Lisboa",
    "kind": "agency",
    "network": null,
    "trading_names": [
      "Sample Homes Lisboa",
      "Sample Homes"
    ],
    "websites": [
      "samplehomes.example"
    ]
  },
  "totals": {
    "towns": 2,
    "properties": 214,
    "portfolio_value_eur": 158500000
  },
  "growth": {
    "quarter": "2026-Q3",
    "new": 79,
    "delisted": 15,
    "new_change_pct": {
      "previous_quarter": 6.7,
      "year_before": 10.4
    },
    "delisted_change_pct": {
      "previous_quarter": -11.8,
      "year_before": null
    }
  },
  "quarters": [
    {
      "quarter": "2026-Q3",
      "new": 79,
      "delisted": 15
    },
    {
      "quarter": "2026-Q2",
      "new": 74,
      "delisted": 17
    },
    {
      "quarter": "2026-Q1",
      "new": 66,
      "delisted": 12
    },
    {
      "quarter": "2025-Q4",
      "new": 58,
      "delisted": 14
    }
  ],
  "towns": [
    {
      "location_id": 101,
      "name": "Lisboa",
      "measures": [
        {
          "type_group": "all",
          "properties": 180,
          "co_listed": 32,
          "share": 0.039,
          "portfolio": {
            "value_eur": 117000000,
            "mean_eur": 650000,
            "median_eur": 560000,
            "min_eur": 173600,
            "max_eur": 2688000,
            "p25_eur": 403200,
            "p75_eur": 789600,
            "price_per_sqm_median_eur": 4746
          },
          "price_changes": {
            "cut": 22,
            "raised": 3,
            "cut_share": 0.12,
            "cut_median_pct": -4.8,
            "raised_median_pct": 3
          },
          "overpricing_at_start": {
            "median_gap_pct": 7.2,
            "share_over_10_pct": 0.24,
            "cut_since_share": 0.41
          },
          "time_on_market": {
            "properties_counted": 180,
            "days_min": 3,
            "days_max": 384,
            "days_median": 96,
            "days_mean": 120
          },
          "ranks": {
            "portfolio_value": {
              "rank": 2,
              "of": 486,
              "percentile": 99.6
            },
            "days_on_market": {
              "rank": 42,
              "of": 486,
              "percentile": 91.4
            }
          }
        }
      ]
    }
  ],
  "towns_total": 2
}

Agencies of a town with the five measures

GET /v1/agencygraph/{country}/benchmark · 75 tokens per page of up to 25 rows (the first 100 agencies of a town) · over MCP: agencygraph_area_benchmark

At most the first 100 agencies of a town in the chosen order (offset + size <= 100); every agency of a town is the city dataset. Figures under 5 properties are null with their count. Growth is new and delisted homes in the latest complete quarter, with the change on the quarter before and a year before.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • size (integer, optional): Query parameter. Page size, at most 25 (a Free plan account is capped lower). 1–25.
  • offset (integer, optional): Query parameter. Position of the next page, copied from the previous response.
  • location_id (integer, required): Query parameter. The town: a town or city's location id from locations_search. ≥ 1.
  • type_group (string, optional): Query parameter. Property type group: all (default), apartment or house. Values: all, apartment, house. default "all".
  • operation (string, optional): Query parameter. sale (default): homes for sale. Rentals are not measured yet. Values: sale. default "sale".
  • sort (string, optional): Query parameter. The measure to sort by. Values: portfolio_value, properties, share, median_price, price_per_sqm, price_cut_share, days_on_market, overpricing. default "portfolio_value".
  • order (string, optional): Query parameter. asc or desc; default the measure's natural order (fewest days on the market first, the rest largest first). Values: asc, desc.
  • min_properties (integer, optional): Query parameter. Leave out agencies with fewer properties (default 5; below 5 the figures are null). ≥ 1; default 5.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/benchmark?size=2&location_id=101&sort=portfolio_value" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "location": {
    "location_id": 101,
    "name": "Lisboa"
  },
  "type_group": "all",
  "sort": "portfolio_value",
  "order": "desc",
  "total": 100,
  "offset": 0,
  "size": 2,
  "next_offset": 2,
  "agencies_in_town": 486,
  "results": [
    {
      "position": 1,
      "agency": {
        "agency_id": "agc_EXAMPLEPRIME00000000000000",
        "name": "Example Prime Estates",
        "kind": "office",
        "network": "Example Network"
      },
      "measures": {
        "type_group": "all",
        "properties": 260,
        "co_listed": 47,
        "share": 0.0563,
        "portfolio": {
          "value_eur": 214000000,
          "mean_eur": 823077,
          "median_eur": 690000,
          "min_eur": 213900,
          "max_eur": 3312000,
          "p25_eur": 496800,
          "p75_eur": 972900,
          "price_per_sqm_median_eur": 5847
        },
        "price_changes": {
          "cut": 31,
          "raised": 5,
          "cut_share": 0.12,
          "cut_median_pct": -5.5,
          "raised_median_pct": 3
        },
        "overpricing_at_start": {
          "median_gap_pct": 9.1,
          "share_over_10_pct": 0.3,
          "cut_since_share": 0.41
        },
        "time_on_market": {
          "properties_counted": 260,
          "days_min": 3,
          "days_max": 472,
          "days_median": 118,
          "days_mean": 148
        },
        "ranks": {
          "portfolio_value": {
            "rank": 1,
            "of": 486,
            "percentile": 99.8
          },
          "days_on_market": {
            "rank": 41,
            "of": 486,
            "percentile": 91.6
          }
        }
      },
      "growth": {
        "quarter": "2026-Q3",
        "new": 71,
        "delisted": 19,
        "new_change_pct": {
          "previous_quarter": 4.4,
          "year_before": 7
        },
        "delisted_change_pct": {
          "previous_quarter": 2.1,
          "year_before": -5
        }
      }
    },
    {
      "position": 2,
      "agency": {
        "agency_id": "agc_EXAMPLEHOMES00000000000000",
        "name": "Sample Homes Lisboa",
        "kind": "agency",
        "network": null
      },
      "measures": {
        "type_group": "all",
        "properties": 180,
        "co_listed": 32,
        "share": 0.039,
        "portfolio": {
          "value_eur": 117000000,
          "mean_eur": 650000,
          "median_eur": 560000,
          "min_eur": 173600,
          "max_eur": 2688000,
          "p25_eur": 403200,
          "p75_eur": 789600,
          "price_per_sqm_median_eur": 4746
        },
        "price_changes": {
          "cut": 22,
          "raised": 3,
          "cut_share": 0.12,
          "cut_median_pct": -4.8,
          "raised_median_pct": 3
        },
        "overpricing_at_start": {
          "median_gap_pct": 7.2,
          "share_over_10_pct": 0.24,
          "cut_since_share": 0.41
        },
        "time_on_market": {
          "properties_counted": 180,
          "days_min": 3,
          "days_max": 384,
          "days_median": 96,
          "days_mean": 120
        },
        "ranks": {
          "portfolio_value": {
            "rank": 2,
            "of": 486,
            "percentile": 99.6
          },
          "days_on_market": {
            "rank": 42,
            "of": 486,
            "percentile": 91.4
          }
        }
      },
      "growth": {
        "quarter": "2026-Q3",
        "new": 64,
        "delisted": 12,
        "new_change_pct": {
          "previous_quarter": 6.7,
          "year_before": 10.7
        },
        "delisted_change_pct": {
          "previous_quarter": -14.3,
          "year_before": null
        }
      }
    }
  ],
  "more": "This town has 486 agencies; the benchmark shows the first 100 in this order. Every agency of the town is the city dataset (GET /v1/agencygraph/pt/datasets?location_id=101)."
}

Agencies' shares of a town's stock and flow

GET /v1/agencygraph/{country}/market-share · 50 tokens per page of up to 25 rows · over MCP: agencygraph_market_share

Each agency's share of the properties on the market in one town, and of the town's new and delisted homes in the latest complete quarter and the quarter before, largest share first. A home two agencies advertise counts for each, so shares can add up to more than 1. Pages of up to 25 agencies.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • size (integer, optional): Query parameter. Page size, at most 25 (a Free plan account is capped lower). 1–25.
  • offset (integer, optional): Query parameter. Position of the next page, copied from the previous response.
  • location_id (integer, required): Query parameter. The town: a town or city's location id from locations_search. ≥ 1.
  • type_group (string, optional): Query parameter. Property type group: all (default), apartment or house. Values: all, apartment, house. default "all".
  • operation (string, optional): Query parameter. sale (default): homes for sale. Rentals are not measured yet. Values: sale. default "sale".

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/es/market-share?size=2&location_id=301" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "ES",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "location": {
    "location_id": 301,
    "name": "Madrid"
  },
  "type_group": "all",
  "quarter": "2026-Q3",
  "town_totals": {
    "quarter": "2026-Q3",
    "new": 9100,
    "delisted": 4300,
    "previous_quarter": {
      "quarter": "2026-Q2",
      "new": 8800,
      "delisted": 4100
    }
  },
  "total": 2380,
  "offset": 0,
  "size": 2,
  "next_offset": 2,
  "results": [
    {
      "position": 1,
      "agency": {
        "agency_id": "agc_EXAMPLECENTRO0000000000000",
        "name": "Example Inmobiliaria Centro",
        "kind": "agency",
        "network": null
      },
      "properties": 310,
      "share": 0.034,
      "new": 355,
      "new_share": 0.039,
      "delisted": 133,
      "delisted_share": 0.0309,
      "previous_quarter": {
        "new_share": 0.034,
        "delisted_share": 0.0293
      }
    },
    {
      "position": 2,
      "agency": {
        "agency_id": "agc_EXAMPLEMADRID0000000000000",
        "name": "Sample Realty Madrid",
        "kind": "office",
        "network": "Example Network"
      },
      "properties": 240,
      "share": 0.028,
      "new": 200,
      "new_share": 0.022,
      "delisted": 112,
      "delisted_share": 0.026,
      "previous_quarter": {
        "new_share": 0.025,
        "delisted_share": 0.0244
      }
    }
  ]
}

The towns where an agency works

GET /v1/agencygraph/{country}/agencies/{agency_id}/territory · 50 tokens per page of up to 25 rows · over MCP: agencygraph_territory

One row per town where an agency has homes on the market: properties, its share of the town, portfolio value and its rank there, and new and delisted homes of the latest complete quarter. Largest first, pages of up to 25 towns.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • agency_id (string, required): Path parameter.
  • size (integer, optional): Query parameter. Page size, at most 25 (a Free plan account is capped lower). 1–25.
  • offset (integer, optional): Query parameter. Position of the next page, copied from the previous response.
  • type_group (string, optional): Query parameter. Property type group: all (default), apartment or house. Values: all, apartment, house. default "all".
  • operation (string, optional): Query parameter. sale (default): homes for sale. Rentals are not measured yet. Values: sale. default "sale".

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/agencies/agc_EXAMPLEHOMES00000000000000/territory" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "agency": {
    "agency_id": "agc_EXAMPLEHOMES00000000000000",
    "name": "Sample Homes Lisboa",
    "kind": "agency",
    "network": null
  },
  "type_group": "all",
  "total": 2,
  "offset": 0,
  "size": 25,
  "next_offset": null,
  "results": [
    {
      "location_id": 101,
      "name": "Lisboa",
      "properties": 180,
      "share": 0.023,
      "portfolio_value_eur": 117000000,
      "portfolio_value_rank": {
        "rank": 2,
        "of": 486,
        "percentile": 99.6
      },
      "growth": {
        "quarter": "2026-Q3",
        "new": 64,
        "delisted": 12,
        "new_change_pct": {
          "previous_quarter": 6.7,
          "year_before": 10.7
        },
        "delisted_change_pct": {
          "previous_quarter": null,
          "year_before": null
        }
      }
    },
    {
      "location_id": 102,
      "name": "Cascais",
      "properties": 34,
      "share": 0.019,
      "portfolio_value_eur": 41500000,
      "portfolio_value_rank": {
        "rank": 9,
        "of": 122,
        "percentile": 92.6
      },
      "growth": {
        "quarter": "2026-Q3",
        "new": 15,
        "delisted": 3,
        "new_change_pct": {
          "previous_quarter": 7.1,
          "year_before": null
        },
        "delisted_change_pct": {
          "previous_quarter": null,
          "year_before": null
        }
      }
    }
  ]
}

A franchise network and its offices

GET /v1/agencygraph/{country}/networks/{brand} · 75 tokens per page of up to 25 rows · over MCP: agencygraph_network

One franchise or brand network in a country (brand, such as agencygraph_resolve_agency returns in network): its totals, and its offices with each one's properties, portfolio value, number of towns and main towns, largest first. location_id narrows it to one town. Pages of up to 25 offices.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • brand (string, required): Path parameter.
  • size (integer, optional): Query parameter. Page size, at most 25 (a Free plan account is capped lower). 1–25.
  • offset (integer, optional): Query parameter. Position of the next page, copied from the previous response.
  • location_id (integer, optional): Query parameter. Optional: only its offices in this town: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/networks/Example%20Network?size=1" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "network": "Example Network",
  "totals": {
    "offices": 58,
    "towns": 74,
    "properties": 4120,
    "portfolio_value_eur": 1630000000
  },
  "total": 58,
  "offset": 0,
  "size": 1,
  "next_offset": 1,
  "results": [
    {
      "office": {
        "agency_id": "agc_EXAMPLEPRIME00000000000000",
        "name": "Example Prime Estates",
        "kind": "office",
        "network": "Example Network"
      },
      "properties": 294,
      "portfolio_value_eur": 255500000,
      "towns": 2,
      "main_towns": [
        {
          "location_id": 101,
          "name": "Lisboa",
          "properties": 260
        },
        {
          "location_id": 102,
          "name": "Cascais",
          "properties": 34
        }
      ]
    }
  ]
}

Screen agencies by ranges of the measures

POST /v1/agencygraph/{country}/screen · 100 tokens per page of up to 25 rows · over MCP: agencygraph_screen_agencies

Filters agencies, one row per agency and town, in the whole country or in up to 20 towns, by ranges of the measures (portfolio value, share, price cut share, days on the market, overpricing), size, network or independence and property type, sorted as you ask, with each row's measures and growth. For recruitment, partners or agencies growing in an area. Pages of up to 25 rows.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).

Request body

  • location_ids (integer[], optional): Optional: up to 20 towns (location ids from locations_search); without, the whole country. at most 20 items; ≥ 1.
  • type_group (string, optional): Property type group: all (default), apartment or house. Values: all, apartment, house. default "all".
  • operation (string, optional): sale (default): homes for sale. Rentals are not measured yet. Values: sale. default "sale".
  • sort (string, optional): The measure to sort by. Values: portfolio_value, properties, share, median_price, price_per_sqm, price_cut_share, days_on_market, overpricing. default "portfolio_value".
  • order (string, optional): asc or desc; default the measure's natural order (fewest days on the market first, the rest largest first). Values: asc, desc.
  • min_properties (integer, optional): Leave out agencies with fewer properties (default 5; below 5 the figures are null). ≥ 1; default 5.
  • max_properties (integer, optional): At most this many properties in the town. ≥ 1.
  • min_portfolio_value_eur (number, optional): At least this portfolio value (EUR).
  • max_portfolio_value_eur (number, optional): At most this portfolio value (EUR).
  • min_share (number, optional): At least this share.
  • max_share (number, optional): At most this share.
  • min_price_cut_share (number, optional): At least this price cut share.
  • max_price_cut_share (number, optional): At most this price cut share.
  • min_days_on_market (number, optional): At least this days on market.
  • max_days_on_market (number, optional): At most this days on market.
  • min_overpricing_pct (number, optional): At least this overpricing (percent).
  • max_overpricing_pct (number, optional): At most this overpricing (percent).
  • independent (boolean, optional): true: only agencies that belong to no network.
  • network (string, optional): Only offices of this network. at most 100 characters.
  • size (integer, optional): Rows per page, 1 to 25 (default 25). 1–25; default 25.
  • offset (integer, optional): Rows to skip: the next_offset of the previous page. ≥ 0; default 0.

Example request

bash
curl -X POST "https://platform.casafari.com/v1/agencygraph/pt/screen" \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"location_ids":[401,402],"independent":true,"min_properties":20,"max_days_on_market":120}'

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "type_group": "all",
  "sort": "portfolio_value",
  "order": "desc",
  "total": 7,
  "offset": 0,
  "size": 25,
  "next_offset": null,
  "results": [
    {
      "agency": {
        "agency_id": "agc_EXAMPLENORTE00000000000000",
        "name": "Sample Imobiliária Norte",
        "kind": "agency",
        "network": null
      },
      "location": {
        "location_id": 401,
        "name": "Sample Municipality A"
      },
      "measures": {
        "type_group": "all",
        "properties": 48,
        "co_listed": 9,
        "share": 0.0828,
        "portfolio": {
          "value_eur": 13900000,
          "mean_eur": 289583,
          "median_eur": 260000,
          "min_eur": 80600,
          "max_eur": 1248000,
          "p25_eur": 187200,
          "p75_eur": 366600,
          "price_per_sqm_median_eur": 2203
        },
        "price_changes": {
          "cut": 5,
          "raised": 1,
          "cut_share": 0.1,
          "cut_median_pct": -3.9,
          "raised_median_pct": 3
        },
        "overpricing_at_start": {
          "median_gap_pct": 5.4,
          "share_over_10_pct": 0.18,
          "cut_since_share": 0.41
        },
        "time_on_market": {
          "properties_counted": 48,
          "days_min": 3,
          "days_max": 328,
          "days_median": 82,
          "days_mean": 102
        },
        "ranks": {
          "portfolio_value": {
            "rank": 3,
            "of": 61,
            "percentile": 95.1
          },
          "days_on_market": {
            "rank": 43,
            "of": 61,
            "percentile": 29.5
          }
        }
      },
      "growth": {
        "quarter": "2026-Q3",
        "new": 22,
        "delisted": 4,
        "new_change_pct": {
          "previous_quarter": 18,
          "year_before": 29.4
        },
        "delisted_change_pct": {
          "previous_quarter": null,
          "year_before": null
        }
      }
    }
  ]
}

What changed for up to 25 agencies since a date

GET /v1/agencygraph/{country}/changes · 25 tokens per call (up to 25 agencies) · over MCP: agencygraph_changes

For up to 25 agency_ids, week by week since a date: new, delisted and relisted homes, price increases and cuts with their median change, and merges into another agency. Keep your own list of agency_ids and call it each week to follow them.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • agency_ids (string, required): Query parameter. Up to 25 agency ids to follow (on REST, comma-separated).
  • since (string, optional): Query parameter. A date within the last year, YYYY-MM-DD (default: a week before the latest weekly build). pattern ^\d{4}-\d{2}-\d{2}$.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/changes?agency_ids=agc_EXAMPLEPRIME00000000000000,agc_EXAMPLEOEIRAS0000000000000&since=2026-10-19" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "since": "2026-10-19",
  "from_week": "2026-W43",
  "results": [
    {
      "agency_id": "agc_EXAMPLEPRIME00000000000000",
      "found": true,
      "agency": {
        "agency_id": "agc_EXAMPLEPRIME00000000000000",
        "name": "Example Prime Estates",
        "kind": "office",
        "network": "Example Network"
      },
      "totals": {
        "new": 8,
        "delisted": 1,
        "relisted": 0,
        "price_up": 0,
        "price_down": 2
      },
      "weeks": [
        {
          "week": "2026-W43",
          "new": 8,
          "delisted": 1,
          "relisted": 0,
          "price_up": 0,
          "price_up_median_pct": null,
          "price_down": 2,
          "price_down_median_pct": -4.5
        }
      ],
      "merges": []
    },
    {
      "agency_id": "agc_EXAMPLEOEIRAS0000000000000",
      "found": true,
      "agency": {
        "agency_id": "agc_EXAMPLEOEIRAS0000000000000",
        "name": "Example Casas Oeiras",
        "kind": "agency",
        "network": null
      },
      "totals": {
        "new": 2,
        "delisted": 0,
        "relisted": 1,
        "price_up": 0,
        "price_down": 11
      },
      "weeks": [
        {
          "week": "2026-W43",
          "new": 2,
          "delisted": 0,
          "relisted": 1,
          "price_up": 0,
          "price_up_median_pct": null,
          "price_down": 11,
          "price_down_median_pct": -6
        }
      ],
      "merges": []
    }
  ]
}

A town's city dataset tier and price

GET /v1/agencygraph/{country}/datasets · Free · REST only

The tier follows the number of agencies measured in the town (large from 2,000, mid-size from 400, small below); buy with POST to datasets/{tier}.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • location_id (integer, required): Query parameter. The town: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/datasets?location_id=102" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "location": {
    "location_id": 102,
    "name": "Cascais"
  },
  "agencies": 650,
  "tier": "mid",
  "tokens": 6250,
  "buy": {
    "method": "POST",
    "path": "/v1/agencygraph/pt/datasets/mid",
    "body": {
      "location_id": 102
    }
  },
  "valid_days": 365,
  "type_groups": [
    "all",
    "apartment",
    "house"
  ]
}

Buy the city dataset of a small city or district

POST /v1/agencygraph/{country}/datasets/small · 2,500 tokens per call · REST only

Body {location_id}. A town of another tier answers 400 naming its tier, not billed. The answer's dataset_id opens the dataset, rebuilt from the newest weekly build, for one year, for this organisation only.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).

Request body

  • location_id (integer, required): The town, whose tier must be small: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl -X POST "https://platform.casafari.com/v1/agencygraph/pt/datasets/small" \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"location_id":401}'

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "dataset_id": "ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
  "location": {
    "location_id": 401,
    "name": "Sample Municipality A"
  },
  "tier": "small",
  "agencies": 120,
  "valid_until": "2027-10-30",
  "download": {
    "json": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
    "csv": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000?format=csv"
  }
}

Buy the city dataset of a mid-size city

POST /v1/agencygraph/{country}/datasets/mid · 6,250 tokens per call · REST only

Body {location_id}. A town of another tier answers 400 naming its tier, not billed. The answer's dataset_id opens the dataset, rebuilt from the newest weekly build, for one year, for this organisation only.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).

Request body

  • location_id (integer, required): The town, whose tier must be mid: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl -X POST "https://platform.casafari.com/v1/agencygraph/pt/datasets/mid" \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"location_id":102}'

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "dataset_id": "ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
  "location": {
    "location_id": 102,
    "name": "Cascais"
  },
  "tier": "mid",
  "agencies": 650,
  "valid_until": "2027-10-30",
  "download": {
    "json": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
    "csv": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000?format=csv"
  }
}

Buy the city dataset of a large city

POST /v1/agencygraph/{country}/datasets/large · 12,500 tokens per call · REST only

Body {location_id}. A town of another tier answers 400 naming its tier, not billed. The answer's dataset_id opens the dataset, rebuilt from the newest weekly build, for one year, for this organisation only.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).

Request body

  • location_id (integer, required): The town, whose tier must be large: a town or city's location id from locations_search. ≥ 1.

Example request

bash
curl -X POST "https://platform.casafari.com/v1/agencygraph/pt/datasets/large" \
  -H "Authorization: Bearer $CASAFARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"location_id":101}'

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "dataset_id": "ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
  "location": {
    "location_id": 101,
    "name": "Lisboa"
  },
  "tier": "large",
  "agencies": 2100,
  "valid_until": "2027-10-30",
  "download": {
    "json": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
    "csv": "/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000?format=csv"
  }
}

Download a bought city dataset (JSON or CSV)

GET /v1/agencygraph/{country}/datasets/{dataset_id} · Free · REST only

Every agency of the town, one row per agency and type group (all, apartment, house): the five measures and new and delisted homes for the last four complete quarters. format=csv answers a CSV file.

Parameters

  • country (string, required): Path parameter. Country, as in every AgencyGraph path: ES or PT (lower case works too).
  • dataset_id (string, required): Path parameter.
  • format (string, optional): Query parameter. json (default) or csv. Values: json, csv. default "json".

Example request

bash
curl "https://platform.casafari.com/v1/agencygraph/pt/datasets/ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000" \
  -H "Authorization: Bearer $CASAFARI_API_KEY"

Example response (200)

Illustrative example: made-up agencies, ids and figures, not real data.

json
{
  "country": "PT",
  "build": {
    "build_id": "agb_EXAMPLEBUILD0000000000001",
    "as_of": "2026-10-26"
  },
  "method_url": "https://developers.casafari.com/docs/agencygraph",
  "dataset_id": "ags_RXhhbXBsZURhdGFzZXQ.EXAMPLESIGNATURE00000000",
  "location": {
    "location_id": 102,
    "name": "Cascais"
  },
  "tier": "mid",
  "valid_until": "2027-10-30",
  "rows": 1950,
  "results": [
    {
      "agency_id": "agc_EXAMPLEPRIME00000000000000",
      "name": "Example Prime Estates",
      "kind": "office",
      "network": "Example Network",
      "type_group": "all",
      "properties": 34,
      "co_listed": 6,
      "share": 0.019,
      "portfolio_value_eur": 41500000,
      "mean_eur": 1220588,
      "median_eur": 940000,
      "min_eur": 290000,
      "max_eur": 4500000,
      "p25_eur": 680000,
      "p75_eur": 1330000,
      "price_per_sqm_median_eur": 6100,
      "price_cut": 4,
      "price_raised": 1,
      "price_cut_share": 0.12,
      "price_cut_median_pct": -5,
      "price_raised_median_pct": 3,
      "overpricing_median_gap_pct": 8,
      "overpricing_share_over_10_pct": 0.29,
      "overpricing_cut_since_share": 0.4,
      "days_on_market_min": 5,
      "days_on_market_max": 410,
      "days_on_market_median": 101,
      "days_on_market_mean": 127,
      "portfolio_value_rank": 9,
      "portfolio_value_of": 650,
      "new_2026-Q3": 15,
      "delisted_2026-Q3": 3,
      "new_2026-Q2": 14,
      "delisted_2026-Q2": 4,
      "new_2026-Q1": 12,
      "delisted_2026-Q1": 2,
      "new_2025-Q4": 11,
      "delisted_2025-Q4": 3
    }
  ]
}

Tip: add .md to any URL to read it as Markdown.