{"openapi":"3.1.0","info":{"title":"Claro API","version":"2026-10-15","description":"Claro AI, Casafari's business expansion search agent: AI search for commercial premises anywhere in Spain, over Casafari's property graph (one record per property, the ads for it merged). Casafari builds the graph from the listings that agencies publish, merging every listing of the same property into one record. Casafari is a real estate data intelligence platform, built for AI agents. The same search is also the Claro MCP server, at POST /mcp.","contact":{"name":"Casafari","url":"https://developers.casafari.com/docs/claro"},"termsOfService":"https://developers.casafari.com/legal/platform-terms"},"servers":[{"url":"https://expansion.casafari.com"}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Your secret API key, pk_... Never use it in a browser."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}},"paths":{"/v1/search":{"post":{"operationId":"search_premises","summary":"Search commercial premises","description":"Find shops, restaurant premises, offices, warehouses and other commercial premises for rent or sale anywhere in Spain. Describe the site in plain words in any language (brief), send criteria as data, or both (criteria override the brief). Returns exact counts (matching, all criteria stated, some not stated), the criteria as understood, and the best results: each with its data, what was met and what its text does not state, the sentence that matched, its coordinates (exact, or snapped to the centre of a ~500 m cell and marked approximate when the agency hides the address; none when it has no pin), a fit verdict read from its text, location figures when your account has location access (footfall, residents, nearby places, and in `location` the footfall split by weekday/weekend, time of day and where the activity comes from live, plus residents by age, households by income and spending power, each null when not stated or unknown, never 0 for unknown; `location_sources` gives each figure's unit, source and vintage, and when it was computed), and the agency's own listing link. Our fit verdict is one input: every raw figure is there for your own scoring. Up to 200 results a page (50 with a publishable key). `next_cursor` gets the next page: send it as `cursor` (alone, with `limit` if you like); the order is fixed when the search runs and stays the same for its 24 hours, so pages never repeat or skip a premises. `page` gives offset, limit and the total ranked. The read-through (`check`) runs only for pages of up to 50. Keep search_id to refine. Keywords only, no model: send just criteria.keywords and/or exclude_keywords (plus any data criteria) with no brief and check: false, e.g. {\"criteria\": {\"operation\": \"rent\", \"cities\": [\"madrid\"], \"keywords\": [[\"salida de humos\", \"sortida de fums\"], [\"esquina\", \"chaflán\"]], \"exclude_keywords\": [\"se traspasa\"]}, \"check\": false}; each keyword group met carries the sentence that matched (evidence) and the phrase it holds (matched).","responses":{"200":{"description":"Search commercial premises","content":{"application/json":{"example":{"search_id":"s_7hQ2","criteria":{"operation":"rent","cities":["madrid"],"area_min":120,"smoke_extraction":true},"counts":{"matching":14,"all_criteria_stated":6,"some_not_stated":8},"not_applied":[],"results":[{"id":"pm_3kX9vQ2LmT8a","title":"Local comercial en esquina","type":"retail","city":"madrid","city_name":"Madrid","district":"Centro","address":null,"location_precision":"approximate","coordinates":{"lat":40.42,"lon":-3.705,"precision":"approximate"},"for_rent":true,"for_sale":false,"rent_eur_month":5000,"sale_eur":null,"area_m2":200,"floor_number":0,"street_level":true,"floors":1,"frontage_m":null,"smoke_outlet":true,"business_transfer":false,"criteria":[{"criterion":"smoke_extraction","status":"met","evidence":"con salida de humos"}],"photos":["https://st2.retelligence.co/c/1234/c/de/abcde350.jpg"],"excerpt":"Local en esquina con salida de humos. Zona de mucho paso.","agency":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"},"location":{"footfall_daily_walk_5min":50000,"footfall_weekday_avg_walk_5min":52000,"footfall_weekend_avg_walk_5min":41000,"residents_walk_10min":20000,"residents_drive_10min":300000,"residents_age_30_44_walk_10min":5200,"households_walk_10min":9000,"households_income_above_57824_walk_10min":null,"spending_power_total_eur_walk_10min":310000000,"spending_power_per_resident_eur_walk_10min":15500,"cafes_walk_5min":12,"transit_stops_walk_5min":5},"location_sources":{"computed_at":"2026-10-12","groups":[{"fields":["footfall_daily_walk_5min","footfall_weekday_avg_walk_5min","footfall_weekend_avg_walk_5min"],"unit":"footfall index: summed per-cell daily count within the walk, not distinct people (weekday/weekend are daily averages; the others split the daily count)","source":"Targomo Footfall estimates (collection 234)","vintage":"2024"},{"fields":["residents_walk_10min","residents_drive_10min","residents_age_30_44_walk_10min"],"unit":"residents","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["households_walk_10min","households_income_above_57824_walk_10min"],"unit":"households (income bands: net household income, EUR a year)","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["spending_power_total_eur_walk_10min"],"unit":"EUR a year","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["spending_power_per_resident_eur_walk_10min"],"unit":"EUR a year per resident (spending_power_total_eur_walk_10min / residents_walk_10min)","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["cafes_walk_5min","transit_stops_walk_5min"],"unit":"places mapped (a count of mapped places, not a census)","source":"OpenStreetMap via Targomo","vintage":"as mapped on computed_at"}]}}],"page":{"offset":0,"limit":200,"total":14},"next_cursor":null,"notes":["The read-through of the results' text (check) runs only for pages of up to 50; results are ranked by criteria and meaning only."]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"brief":{"type":"string","description":"The site brief in plain words, e.g. \"burger restaurant, corner unit 120-250 m², smoke outlet, busy street, Madrid, rent under 8,000 a month\"."},"criteria":{"type":"object","additionalProperties":false,"description":"Criteria as data. Hard criteria (operation, cities, types, price, area) exclude properties outside them; the rest exclude only properties that state the opposite, and each result says which were met and which the property does not state.","properties":{"operation":{"type":"string","enum":["rent","sale","either"]},"cities":{"type":"array","items":{"type":"string"},"description":"Spanish towns or cities by name or slug (\"valencia\", \"Palma\"). Leave out for all of Spain."},"provinces":{"type":"array","items":{"type":"string","enum":["a-coruna","alava","albacete","alicante","almeria","asturias","avila","badajoz","barcelona","burgos","caceres","cadiz","cantabria","castellon","ceuta","ciudad-real","cordoba","cuenca","girona","granada","guadalajara","guipuzcoa","huelva","huesca","islas-baleares","jaen","la-rioja","las-palmas","leon","lleida","lugo","madrid","malaga","melilla","murcia","navarra","ourense","palencia","pontevedra","salamanca","santa-cruz-de-tenerife","segovia","sevilla","soria","tarragona","teruel","toledo","valencia","valladolid","vizcaya","zamora","zaragoza"]},"description":"Provinces; a property must be in one of them."},"districts":{"type":"array","items":{"type":"string"},"description":"Named districts or neighbourhoods in the cities (Centro, Malasaña, Chamberí, Eixample, Gràcia, Poblenou...). A property outside them is out; one that does not state its district stays, marked not stated."},"types":{"type":"array","items":{"type":"string","enum":["hotel","retail","warehouse","industrial","office","other_commercial"]}},"area_min":{"type":"number"},"area_max":{"type":"number"},"price_min":{"type":"number","description":"EUR: a month for rent, the total for a sale; applies to each operation without its own rent_/sale_ limit."},"price_max":{"type":"number"},"rent_price_min":{"type":"number","description":"EUR a month; compared only with rents."},"rent_price_max":{"type":"number","description":"EUR a month; compared only with rents. With sale_price_max, operation \"either\" keeps a property whose rent or sale price fits its own limit."},"sale_price_min":{"type":"number","description":"EUR total; compared only with sale prices."},"sale_price_max":{"type":"number"},"price_m2_min":{"type":"number","description":"EUR per m² of the property's area (a month for rent); a property with no stated area is \"not stated\"."},"price_m2_max":{"type":"number"},"rent_price_m2_min":{"type":"number"},"rent_price_m2_max":{"type":"number"},"sale_price_m2_min":{"type":"number"},"sale_price_m2_max":{"type":"number"},"street_level":{"type":"boolean"},"frontage_min_m":{"type":"number","description":"Facade length (fachada) in metres."},"frontage_max_m":{"type":"number"},"floors_min":{"type":"number","description":"Number of floors (plantas) the premises has."},"floors_max":{"type":"number"},"ceiling_min_m":{"type":"number"},"smoke_extraction":{"type":"boolean"},"corner":{"type":"boolean"},"shop_window":{"type":"boolean"},"open_plan":{"type":"boolean"},"step_free":{"type":"boolean"},"loading_access":{"type":"boolean"},"licence":{"type":"string","enum":["food_service","retail","office","gym","none"]},"licence_activities":{"type":"array","items":{"type":"string"},"description":"Activities its licence sentence must name, in Spanish or Catalan: cafetería, panadería, restaurante..."},"transfer_price_min":{"type":"number","description":"Transfer fee (traspaso) in EUR; met when its stated range overlaps."},"transfer_price_max":{"type":"number"},"business_transfer":{"type":"boolean","description":"true: only business transfers (traspasos); false: none."},"business_types":{"type":"array","items":{"type":"string"},"description":"Uses its text says it suits, in English: restaurant, cafe, gym..."},"keywords":{"type":"array","items":{"type":"array","items":{"type":"string"}},"description":"Groups of phrases; a property meets a group when its text holds any phrase. Write phrases as Spanish agencies do."},"exclude_keywords":{"type":"array","items":{"type":"string"},"description":"Leave out properties whose text holds any of these."},"footfall_min":{"type":"number","description":"Minimum footfall index within a 5-minute walk (an index of pedestrian activity that compares places; not a head count). Needs location data access."},"pop_walk10_min":{"type":"number","description":"Residents within a 10-minute walk. Needs location data access."},"pop_drive10_min":{"type":"number","description":"Residents within a 10-minute drive. Needs location data access."},"transit_min":{"type":"number","description":"Stations and stops within a 5-minute walk. Needs location data access."},"competitors_max":{"type":"array","description":"At most this many places of a kind within a 5-minute walk (gyms: 10). Needs location data access.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["restaurants","fast_food","cafes","shops","supermarkets","gyms"]},"max":{"type":"number"}},"required":["kind","max"]}},"own_stores_away_m":{"type":"number","description":"No store from your own list (upload it with PUT /v1/stores) within this many metres of the premises, straight-line, 1-1,000. Needs an exact pin."},"competitors_near_max":{"type":"array","description":"At most `max` businesses of a segment (or of the named `chains`) within `within_m` straight-line metres (1-1,000), from Overture Maps places. A property with an approximate pin gets no verdict.","items":{"type":"object","properties":{"segment":{"type":"string","enum":["gym","burger","fast_food","coffee","bakery","pharmacy","supermarket","fashion","pizza"]},"within_m":{"type":"number"},"max":{"type":"number"},"chains":{"type":"array","items":{"type":"string"},"description":"Only these brands count (rivals or your own), e.g. Burger King, Basic-Fit. Matched on Overture brand and name."}},"required":["segment","within_m","max"]}},"spending_per_resident_min":{"type":"number","description":"Spending power a resident a year (EUR) within a 10-minute walk. Needs location data access."},"high_income_share_min":{"type":"number","description":"% of households within a 10-minute walk with net income above 40,162 EUR a year. Needs location data access."},"age_shares_min":{"type":"array","description":"Minimum % of residents within a 10-minute walk in an age band. Needs location data access.","items":{"type":"object","properties":{"band":{"type":"string","enum":["0_14","15_29","30_44","45_59","60p"]},"min_pct":{"type":"number"}},"required":["band","min_pct"]}},"meaning":{"type":"string","description":"A wish no field holds, in any language; ranks results, never filters."},"sort":{"type":"string","enum":["best","price_asc","price_desc","area_desc","footfall_desc","supply_gap"],"description":"supply_gap ranks where residents per similar place is highest (residents within a 10-minute walk / (places within gap_radius_m, 600 m by default, + 1)); needs gap_segment or one competitors_near_max segment. Needs location data access; unscored properties go last."},"gap_segment":{"type":"string","enum":["gym","burger","fast_food","coffee","bakery","pharmacy","supermarket","fashion","pizza"],"description":"The business kind the supply_gap sort counts."},"gap_radius_m":{"type":"integer","enum":[300,600],"description":"Radius in metres in which the supply_gap sort counts similar places: 600 (default) or 300 (about a 5-minute walk). Only with sort supply_gap."}}},"limit":{"type":"integer","minimum":1,"maximum":200,"default":10,"description":"Results a page, up to 200; above 50 check is off."},"cursor":{"type":"string","description":"next_cursor from an earlier answer: returns that search's next page, same criteria and order. Send without brief, criteria or change."},"check":{"type":"boolean","default":true,"description":"Read the top results' text against the brief (adds a few seconds). Off above 50 results a page and on later pages."},"insights":{"type":"boolean","default":false,"description":"Add `insights`, charts as data over every match, each with a one-sentence answer, its count, scope, source and date: per criterion how many matches meet it, leave it unsaid or contradict it (and how many would state everything without it); with one price limit, what it reaches among premises of this kind and place before the limit, else what the matches ask per m²; and where the matches are by district or town. Asking prices; each unit counted once."}}},"examples":{"keywords_only":{"summary":"Keywords only, no brief: no model call","value":{"criteria":{"operation":"rent","cities":["madrid"],"keywords":[["salida de humos","sortida de fums"],["esquina","chaflán"]],"exclude_keywords":["se traspasa"]},"check":false}}}}}}}},"/v1/search/refine":{"post":{"operationId":"refine_search","summary":"Refine a search","description":"Change part of an earlier search in plain words (\"bigger, at least 200 m²\", \"Barcelona too\", \"drop the corner\") and run it again, as a new search with its own search_id and pages. Uses the search_id from search_premises; searches are kept 24 hours. Results as search_premises gives them, location figures with `location_sources`. Up to 200 results a page (50 with a publishable key). `next_cursor` gets the next page: send it as `cursor` (alone, with `limit` if you like); the order is fixed when the search runs and stays the same for its 24 hours, so pages never repeat or skip a premises. `page` gives offset, limit and the total ranked. The read-through (`check`) runs only for pages of up to 50.","responses":{"200":{"description":"Refine a search","content":{"application/json":{"example":{"search_id":"s_7hQ2","criteria":{"operation":"rent","cities":["madrid"],"area_min":120,"smoke_extraction":true},"counts":{"matching":14,"all_criteria_stated":6,"some_not_stated":8},"not_applied":[],"results":[{"id":"pm_3kX9vQ2LmT8a","title":"Local comercial en esquina","type":"retail","city":"madrid","city_name":"Madrid","district":"Centro","address":null,"location_precision":"approximate","coordinates":{"lat":40.42,"lon":-3.705,"precision":"approximate"},"for_rent":true,"for_sale":false,"rent_eur_month":5000,"sale_eur":null,"area_m2":200,"floor_number":0,"street_level":true,"floors":1,"frontage_m":null,"smoke_outlet":true,"business_transfer":false,"criteria":[{"criterion":"smoke_extraction","status":"met","evidence":"con salida de humos"}],"photos":["https://st2.retelligence.co/c/1234/c/de/abcde350.jpg"],"excerpt":"Local en esquina con salida de humos. Zona de mucho paso.","agency":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"},"location":{"footfall_daily_walk_5min":50000,"footfall_weekday_avg_walk_5min":52000,"footfall_weekend_avg_walk_5min":41000,"residents_walk_10min":20000,"residents_drive_10min":300000,"residents_age_30_44_walk_10min":5200,"households_walk_10min":9000,"households_income_above_57824_walk_10min":null,"spending_power_total_eur_walk_10min":310000000,"spending_power_per_resident_eur_walk_10min":15500,"cafes_walk_5min":12,"transit_stops_walk_5min":5},"location_sources":{"computed_at":"2026-10-12","groups":[{"fields":["footfall_daily_walk_5min","footfall_weekday_avg_walk_5min","footfall_weekend_avg_walk_5min"],"unit":"footfall index: summed per-cell daily count within the walk, not distinct people (weekday/weekend are daily averages; the others split the daily count)","source":"Targomo Footfall estimates (collection 234)","vintage":"2024"},{"fields":["residents_walk_10min","residents_drive_10min","residents_age_30_44_walk_10min"],"unit":"residents","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["households_walk_10min","households_income_above_57824_walk_10min"],"unit":"households (income bands: net household income, EUR a year)","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["spending_power_total_eur_walk_10min"],"unit":"EUR a year","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["spending_power_per_resident_eur_walk_10min"],"unit":"EUR a year per resident (spending_power_total_eur_walk_10min / residents_walk_10min)","source":"Targomo, MB Research sociodemographics (collection 87)","vintage":"2024"},{"fields":["cafes_walk_5min","transit_stops_walk_5min"],"unit":"places mapped (a count of mapped places, not a census)","source":"OpenStreetMap via Targomo","vintage":"as mapped on computed_at"}]}}],"page":{"offset":0,"limit":200,"total":14},"next_cursor":null,"notes":["The read-through of the results' text (check) runs only for pages of up to 50; results are ranked by criteria and meaning only."]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["search_id"],"properties":{"search_id":{"type":"string"},"change":{"type":"string","description":"What to change, in plain words. Required unless cursor is sent."},"limit":{"type":"integer","minimum":1,"maximum":200,"default":10,"description":"Results a page, up to 200; above 50 check is off."},"cursor":{"type":"string","description":"next_cursor from an earlier answer: returns that search's next page, same criteria and order. Send without brief, criteria or change."},"check":{"type":"boolean","default":true},"insights":{"type":"boolean","default":false,"description":"Add `insights`, charts as data over every match, each with a one-sentence answer, its count, scope, source and date: per criterion how many matches meet it, leave it unsaid or contradict it (and how many would state everything without it); with one price limit, what it reaches among premises of this kind and place before the limit, else what the matches ask per m²; and where the matches are by district or town. Asking prices; each unit counted once."}}}}}}}},"/v1/premises/{id}":{"get":{"operationId":"get_premises","summary":"Get one premises","description":"One premises in full by the id a search returned: its data, facts read from its text with the sentence each came from (fact_sources), its coordinates (exact, or approximate: snapped to a ~500 m cell), location figures (with location access), an excerpt, up to 8 photos (`photos`: Casafari thumbnail URLs; search results carry the first 4, and `photo_source` names the advertiser and page they come from), and the agency's own listing link (`agency_links` lists every agency's own page for the premises, never a portal's, earliest first). `energy` is the energy certificate as the ad advertises it, unverified: not checked against the official register (rating and emissions rating A to G, kWh/m² and kg CO2/m² a year, each null when not stated; null until read); `energy.official` is the regional register's certificate, only when it is matched on this unit and declares commercial use, with the register and the attribution its licence asks for (else null). `status` says whether it is still on the market. `timeline` gives when it was first listed (`listed_since`, `days_listed`) and, per live operation, the first and current asking price, the number of price cuts, the change in percent and the asking-price periods (`history`); null fields are not stated.","responses":{"200":{"description":"Get one premises","content":{"application/json":{"example":{"id":"pm_3kX9vQ2LmT8a","title":"Local comercial en esquina","type":"retail","city":"madrid","city_name":"Madrid","district":"Centro","address":null,"location_precision":"approximate","coordinates":{"lat":40.42,"lon":-3.705,"precision":"approximate"},"for_rent":true,"for_sale":false,"rent_eur_month":5000,"sale_eur":null,"area_m2":200,"floor_number":0,"street_level":true,"floors":1,"frontage_m":null,"smoke_outlet":true,"business_transfer":false,"criteria":[{"criterion":"smoke_extraction","status":"met","evidence":"con salida de humos"}],"photos":["https://st2.retelligence.co/c/1234/c/de/abcde350.jpg"],"excerpt":"Local en esquina con salida de humos. Zona de mucho paso.","agency":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"},"status":"active","fact_sources":{"smoke_extraction":"con salida de humos"},"agency_links":[{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"},{"name":"Inmobiliaria Luna","listing_url":"https://inmobiliarialuna.es/ref/42"}],"photo_source":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"},"timeline":{"listed_since":"2026-03-02","days_listed":226,"rent":{"first":4200,"current":3800,"cuts":2,"change_pct":-9.5,"history":[{"from":"2026-03-02","to":"2026-04-20","price":4200},{"from":"2026-04-21","to":"2026-06-09","price":4000},{"from":"2026-06-10","to":null,"price":3800}]},"sale":null,"source":"listings","as_of":"2026-10-14"},"energy":{"rating":"C","consumption_kwh_m2":142.3,"emissions_kg_m2":31,"emissions_rating":"D","source":"listing","as_of":"2026-10-14","official":{"rating":"D","emissions_rating":"C","consumption_kwh_m2":182.4,"emissions_kg_m2":30.1,"issued":"2023-05-04","valid_until":"2033-05-04","register":"Madrid's energy certificate register","licence":"CC BY 4.0","attribution":"Fuente de los datos: Comunidad de Madrid. CC BY 4.0","match":"unit","use":"commercial","climate_zone":"D3","heating":null,"hot_water":null,"renewables":null,"yearly_cost_eur":null,"as_of":"2026-10-15"}},"insights":[{"id":"site_assessment","kind":"assessment","title":"A 200 m² street-level corner unit in Centro, asking €25/m² a month against a median of €21.5/m² for 38 comparables.","n":41,"scope":"with_location","source":"Written by gemini-3.1-flash-lite from the figures on this page; every number checked against them","as_of":"2026-10-14","summary":["A 200 m² street-level corner unit in Centro, asking €25/m² a month against a median of €21.5/m² for 38 comparables.","The footfall index here is higher than 82% of the retail premises in Madrid.","Its text states a smoke outlet."],"strengths":[{"text":"The footfall index is higher than 82% of the retail premises in Madrid.","keys":["rank.footfall","footfall_daily_walk_5min"]}],"watchouts":[{"text":"3 coffee places within 500 m.","keys":["competition.coffee"]}],"segments":[{"segment":"qsr","verdict":"strong","why":[{"text":"Its text states a smoke outlet, and the unit is at street level.","keys":["listing.smoke_extraction","listing.street_level"]},{"text":"4 fast-food places within a 5-minute walk.","keys":["fast_food_walk_5min"]}]},{"segment":"coffee","verdict":"fair","why":[{"text":"3 coffee places within 500 m.","keys":["competition.coffee"]},{"text":"The asking price of €25/m² a month is higher than 63% of the 38 comparables.","keys":["market.rent_vs_market"]}]},{"segment":"clinic","verdict":"not_assessable","why":[]},{"segment":"fitness","verdict":"not_assessable","why":[]},{"segment":"retail","verdict":"fair","why":[{"text":"A street-level corner unit of 200 m².","keys":["listing.corner","listing.area_m2"]}]},{"segment":"supermarket","verdict":"not_assessable","why":[]}],"model":"gemini-3.1-flash-lite","prompt_version":3,"inputs_hash":"9f2c…","generated_at":"2026-10-14T10:00:00Z","notes":["1 sentence dropped: a number not in the figures given."]},{"id":"rent_vs_market","kind":"histogram","title":"€25.0/m² a month: above the median of 38 comparable retail premises for rent in Centro (€21.5/m²); dearer than 63% of them.","n":38,"scope":"retail premises for rent in Centro, 100–400 m² (half to twice this size), each unit counted once","source":"Claro properties on the market; asking rents, not agreed ones","as_of":"2026-10-13","unit":"eur_m2_month","bins":[{"from":10,"to":15,"n":6},{"from":15,"to":20,"n":9},{"from":20,"to":25,"n":11},{"from":25,"to":30,"n":8},{"from":30,"to":35,"n":4}],"open_high":true,"median":21.5,"p25":17.8,"p75":27,"marker":{"value":25,"label":"this premises","percentile":63}},{"id":"prices_here","kind":"table","title":"Retail premises for rent in Salamanca ask a median of €24.5/m² a month; the middle half ask €18.0/m² a month to €33.0/m² a month (212 with a stated price and size).","n":308,"place":{"name":"Salamanca","level":"district"},"rows":[{"operation":"rent","n":212,"p25":18,"median":24.5,"p75":33,"unit":"eur_m2_month"},{"operation":"sale","n":96,"p25":2100,"median":3150,"p75":4400,"unit":"eur_m2"}],"city":{"name":"Madrid","rows":[{"operation":"rent","n":2710,"p25":13.2,"median":18.9,"p75":26.4,"unit":"eur_m2_month"}]},"by_size":[{"band":"Under 80 m²","operation":"rent","n":70,"median":27,"unit":"eur_m2_month"}],"scope":"Active retail premises that name Salamanca, with a stated price and size, each unit once; a median from 5 and quartiles from 10","source":"Claro properties on the market; asking prices, not agreed ones","as_of":"2026-10-14"},{"id":"supply_flow","kind":"bars","title":"4,120 retail premises for rent on the market in Madrid on 13 Oct 2026; 96 came on and 71 left from 8 Oct 2026 to 13 Oct 2026; the median asking price went from €18.9/m² a month to €19.0/m² a month.","n":4120,"place":{"name":"Madrid","level":"town"},"operation":"rent","days":30,"recorded":6,"from":"2026-10-08","to":"2026-10-13","active":4120,"new":96,"withdrawn":71,"median_start":18.9,"median_end":19,"unit":"eur_m2_month","rows":[{"label":"On the market","n":4120,"median":null},{"label":"Came on","n":96,"median":null},{"label":"Left","n":71,"median":null}],"scope":"Retail premises for rent in Madrid, from 8 Oct 2026 to 13 Oct 2026: units on the market each counted once; properties that came on and left summed by day","source":"Claro's nightly count of its properties (market_daily); asking prices","as_of":"2026-10-14","notes":["Only 6 days recorded: Claro's daily count of the market starts on 8 Oct 2026, so these figures cover less than a week, not 30 days."]},{"id":"time_on_market","kind":"bars","title":"Retail premises for rent within 1 km stay 143 days on the market on average (58 properties); longest at €8,000 and over a month, 210 days.","n":58,"radius_m":1000,"type":"retail","operation":"rent","avg_days":143,"rows":[{"band":"under €2,000 a month","avg_days":84,"n":31,"label":"Under €2,000 a month","median":null},{"band":"€8,000 and over a month","avg_days":210,"n":27,"label":"€8,000 and over a month","median":null}],"scope":"Retail premises for rent listed within 1,000 m, by asking rent band, every property recorded","source":"Casafari Area Insights; average days on the market by asking price","as_of":"2026-10-14"},{"id":"similar","kind":"list","title":"6 similar retail premises for rent within 1.5 km, nearest first.","n":6,"level":"radius","scope":"Retail premises for rent, 100–400 m² (half to twice this size), within 1.5 km of this premises, then in Centro, then in Madrid, widening only until 6 are found; each unit counted once, never this one. Used: within 1.5 km","source":"Claro properties on the market; asking prices","as_of":"2026-10-14","rows":[{"id":"pm_bbbbbbbbbbbbbbbbbbbbbb","title":"Local a pie de calle","district":"Centro","city":"Madrid","distance_m":420,"precision":"exact","area_m2":120,"rent_eur_month":3900,"sale_eur":null,"eur_m2":32.5,"eur_m2_unit":"eur_m2_month","photo":"https://st2.retelligence.co/c/12/b/cd/abcd350.jpg","agency":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/7"},"listed_since":null}]},{"id":"scorecard","kind":"scorecard","title":"21 of 34 location figures ranked against the retail premises in Madrid; the highest, footfall index, average day, is above 82% of them.","n":2140,"scope":"Each figure against the retail premises in Madrid and the retail premises in Centro with that figure measured; a missing figure, or a 0 footfall or population, is left out, never ranked as low","source":"Targomo, MB Research 2024; Targomo footfall 2024 (footfall index); Targomo points of interest, © OpenStreetMap contributors","as_of":"2026-10-15","within":{"city":"retail premises in Madrid","district":"retail premises in Centro"},"groups":[{"key":"daytime","label":"Footfall and daytime","rows":[{"key":"footfall_daily_walk_5min","label":"Footfall index, average day","value":48210,"unit":"index","scope":"Footfall index within a 5-minute walk; compares places, not a head count","source":"Targomo footfall 2024 (footfall index)","as_of":"2026-10-12","origin":"stored","city":{"percentile":82,"n":2140},"district":{"percentile":55,"n":212}},{"key":"footfall_weekend_vs_weekday_pct","label":"Weekend day against weekday","value":-12,"unit":"pct","scope":"Footfall index within a 5-minute walk; compares places, not a head count; change in %","source":"Targomo footfall 2024 (footfall index)","as_of":"2026-10-15","origin":"live","city":null,"district":null,"note":"Asked for this point only, not stored for other properties, so not ranked."}]}],"strongest":["footfall_daily_walk_5min","restaurants_walk_5min","transit_stops_walk_5min","cafes_walk_5min","shops_walk_5min"],"weakest":["residents_age_0_14_pct_walk_10min","households_walk_10min","gyms_walk_10min","supermarkets_walk_5min","residents_drive_10min"]}]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"insights","in":"query","required":false,"schema":{"type":"string","enum":["1"]},"description":"1 adds `insights`: the page's charts as data."},{"name":"segments","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated business kinds to list first in the distances chart, e.g. burger,coffee."},{"name":"assessment","in":"query","required":false,"schema":{"type":"string","enum":["1"]},"description":"With insights=1: 1 adds `site_assessment` first in `insights` (see the get_premises tool's `assessment`)."}]}},"/v1/compare":{"post":{"operationId":"compare_premises","summary":"Compare premises","description":"2 to 10 premises side by side, by the ids a search returned.","responses":{"200":{"description":"Compare premises","content":{"application/json":{"example":{"premises":[{"id":"pm_3kX9vQ2LmT8a","title":"Local comercial en esquina","type":"retail","city":"madrid","city_name":"Madrid","district":"Centro","address":null,"location_precision":"approximate","coordinates":{"lat":40.42,"lon":-3.705,"precision":"approximate"},"for_rent":true,"for_sale":false,"rent_eur_month":5000,"sale_eur":null,"area_m2":200,"floor_number":0,"street_level":true,"floors":1,"frontage_m":null,"smoke_outlet":true,"business_transfer":false,"criteria":[{"criterion":"smoke_extraction","status":"met","evidence":"con salida de humos"}],"photos":["https://st2.retelligence.co/c/1234/c/de/abcde350.jpg"],"excerpt":"Local en esquina con salida de humos. Zona de mucho paso.","agency":{"name":"Agencia Sol","listing_url":"https://agenciasol.es/1"}}],"missing":[]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":2,"maxItems":10}}}}}}}},"/v1/location":{"post":{"operationId":"explain_location","summary":"Location figures","description":"Footfall index (an index of pedestrian activity within a 5-minute walk that compares places with each other; not a head count, never people or visitors a day; split into weekday and weekend averages, morning/lunch/afternoon/evening and local/commuter/tourist shares of the index), residents within a 10-minute walk and drive (by age band 0-14, 15-29, 30-44, 45-59, 60+, with households, households per net income quintile and total spending power within a 10-minute walk), and nearby restaurants, fast food, cafes, shops, supermarkets, gyms and transit stops, for a premises id or any point (lat, lon) in Spain. Needs location data access on your account; a point that is not a premises is a live call on your account's location key (about 31 Targomo operations per point). A figure Targomo has no data for is null, never 0.","responses":{"200":{"description":"Location figures","content":{"application/json":{"example":{"point":{"lat":40.42,"lon":-3.7},"source":"precomputed","figures":{"footfall_daily":50000,"pop_walk10":20000,"pop_drive10":300000,"restaurants_walk5":30,"transit_walk5":5,"footfall_weekday":52000,"footfall_weekend":41000,"footfall_tourist":9000,"pop_age_30_44":5200,"households_walk10":9000,"income_q3":1800,"spending_power_walk10":310000000}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"}}}}}}}},"/v1/market":{"post":{"operationId":"market_snapshot","summary":"What premises ask in a place","description":"What commercial premises of a kind ask in a place anywhere in Spain, from every active property of that kind and place (each unit counted once): the asking price per m² as a distribution with its median and middle half, by size band, by district or town, and for one town or province the monthly average over three years with the change in a year, the properties on the market and their days on the market (Casafari Area Insights). Ask in plain words (question: \"what does retail rent for in Chamberí?\") or send criteria as data (place, types, operation, optional size range); other criteria are ignored. Asking prices, not agreed ones; at least 10 properties or no figures. Returns the criteria as understood and `insights`: charts as data, each with a one-sentence answer, its count, scope, source and date.","responses":{"200":{"description":"What premises ask in a place","content":{"application/json":{"example":{"criteria":{"operation":"rent","cities":["madrid"],"districts":["Chamberí"],"types":["retail"]},"insights":[{"id":"market","kind":"histogram","title":"Retail premises for rent in Chamberí, Madrid ask a median of €21.0/m² a month; the middle half ask €17.2/m²–€26.4/m² (52 with a stated rent and size).","n":38,"scope":"retail premises for rent in Centro, 100–400 m² (half to twice this size), each unit counted once","source":"Claro properties on the market; asking rents, not agreed ones","as_of":"2026-10-13","unit":"eur_m2_month","bins":[{"from":10,"to":15,"n":6},{"from":15,"to":20,"n":9},{"from":20,"to":25,"n":11},{"from":25,"to":30,"n":8},{"from":30,"to":35,"n":4}],"open_high":true,"median":21.5,"p25":17.8,"p75":27}],"notes":[]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"question":{"type":"string","description":"The question in plain words, any language: \"what do offices rent for in Valencia?\""},"criteria":{"type":"object","additionalProperties":false,"description":"Criteria as data. Hard criteria (operation, cities, types, price, area) exclude properties outside them; the rest exclude only properties that state the opposite, and each result says which were met and which the property does not state.","properties":{"operation":{"type":"string","enum":["rent","sale","either"]},"cities":{"type":"array","items":{"type":"string"},"description":"Spanish towns or cities by name or slug (\"valencia\", \"Palma\"). Leave out for all of Spain."},"provinces":{"type":"array","items":{"type":"string","enum":["a-coruna","alava","albacete","alicante","almeria","asturias","avila","badajoz","barcelona","burgos","caceres","cadiz","cantabria","castellon","ceuta","ciudad-real","cordoba","cuenca","girona","granada","guadalajara","guipuzcoa","huelva","huesca","islas-baleares","jaen","la-rioja","las-palmas","leon","lleida","lugo","madrid","malaga","melilla","murcia","navarra","ourense","palencia","pontevedra","salamanca","santa-cruz-de-tenerife","segovia","sevilla","soria","tarragona","teruel","toledo","valencia","valladolid","vizcaya","zamora","zaragoza"]},"description":"Provinces; a property must be in one of them."},"districts":{"type":"array","items":{"type":"string"},"description":"Named districts or neighbourhoods in the cities (Centro, Malasaña, Chamberí, Eixample, Gràcia, Poblenou...). A property outside them is out; one that does not state its district stays, marked not stated."},"types":{"type":"array","items":{"type":"string","enum":["hotel","retail","warehouse","industrial","office","other_commercial"]}},"area_min":{"type":"number"},"area_max":{"type":"number"},"price_min":{"type":"number","description":"EUR: a month for rent, the total for a sale; applies to each operation without its own rent_/sale_ limit."},"price_max":{"type":"number"},"rent_price_min":{"type":"number","description":"EUR a month; compared only with rents."},"rent_price_max":{"type":"number","description":"EUR a month; compared only with rents. With sale_price_max, operation \"either\" keeps a property whose rent or sale price fits its own limit."},"sale_price_min":{"type":"number","description":"EUR total; compared only with sale prices."},"sale_price_max":{"type":"number"},"price_m2_min":{"type":"number","description":"EUR per m² of the property's area (a month for rent); a property with no stated area is \"not stated\"."},"price_m2_max":{"type":"number"},"rent_price_m2_min":{"type":"number"},"rent_price_m2_max":{"type":"number"},"sale_price_m2_min":{"type":"number"},"sale_price_m2_max":{"type":"number"},"street_level":{"type":"boolean"},"frontage_min_m":{"type":"number","description":"Facade length (fachada) in metres."},"frontage_max_m":{"type":"number"},"floors_min":{"type":"number","description":"Number of floors (plantas) the premises has."},"floors_max":{"type":"number"},"ceiling_min_m":{"type":"number"},"smoke_extraction":{"type":"boolean"},"corner":{"type":"boolean"},"shop_window":{"type":"boolean"},"open_plan":{"type":"boolean"},"step_free":{"type":"boolean"},"loading_access":{"type":"boolean"},"licence":{"type":"string","enum":["food_service","retail","office","gym","none"]},"licence_activities":{"type":"array","items":{"type":"string"},"description":"Activities its licence sentence must name, in Spanish or Catalan: cafetería, panadería, restaurante..."},"transfer_price_min":{"type":"number","description":"Transfer fee (traspaso) in EUR; met when its stated range overlaps."},"transfer_price_max":{"type":"number"},"business_transfer":{"type":"boolean","description":"true: only business transfers (traspasos); false: none."},"business_types":{"type":"array","items":{"type":"string"},"description":"Uses its text says it suits, in English: restaurant, cafe, gym..."},"keywords":{"type":"array","items":{"type":"array","items":{"type":"string"}},"description":"Groups of phrases; a property meets a group when its text holds any phrase. Write phrases as Spanish agencies do."},"exclude_keywords":{"type":"array","items":{"type":"string"},"description":"Leave out properties whose text holds any of these."},"footfall_min":{"type":"number","description":"Minimum footfall index within a 5-minute walk (an index of pedestrian activity that compares places; not a head count). Needs location data access."},"pop_walk10_min":{"type":"number","description":"Residents within a 10-minute walk. Needs location data access."},"pop_drive10_min":{"type":"number","description":"Residents within a 10-minute drive. Needs location data access."},"transit_min":{"type":"number","description":"Stations and stops within a 5-minute walk. Needs location data access."},"competitors_max":{"type":"array","description":"At most this many places of a kind within a 5-minute walk (gyms: 10). Needs location data access.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["restaurants","fast_food","cafes","shops","supermarkets","gyms"]},"max":{"type":"number"}},"required":["kind","max"]}},"own_stores_away_m":{"type":"number","description":"No store from your own list (upload it with PUT /v1/stores) within this many metres of the premises, straight-line, 1-1,000. Needs an exact pin."},"competitors_near_max":{"type":"array","description":"At most `max` businesses of a segment (or of the named `chains`) within `within_m` straight-line metres (1-1,000), from Overture Maps places. A property with an approximate pin gets no verdict.","items":{"type":"object","properties":{"segment":{"type":"string","enum":["gym","burger","fast_food","coffee","bakery","pharmacy","supermarket","fashion","pizza"]},"within_m":{"type":"number"},"max":{"type":"number"},"chains":{"type":"array","items":{"type":"string"},"description":"Only these brands count (rivals or your own), e.g. Burger King, Basic-Fit. Matched on Overture brand and name."}},"required":["segment","within_m","max"]}},"spending_per_resident_min":{"type":"number","description":"Spending power a resident a year (EUR) within a 10-minute walk. Needs location data access."},"high_income_share_min":{"type":"number","description":"% of households within a 10-minute walk with net income above 40,162 EUR a year. Needs location data access."},"age_shares_min":{"type":"array","description":"Minimum % of residents within a 10-minute walk in an age band. Needs location data access.","items":{"type":"object","properties":{"band":{"type":"string","enum":["0_14","15_29","30_44","45_59","60p"]},"min_pct":{"type":"number"}},"required":["band","min_pct"]}},"meaning":{"type":"string","description":"A wish no field holds, in any language; ranks results, never filters."},"sort":{"type":"string","enum":["best","price_asc","price_desc","area_desc","footfall_desc","supply_gap"],"description":"supply_gap ranks where residents per similar place is highest (residents within a 10-minute walk / (places within gap_radius_m, 600 m by default, + 1)); needs gap_segment or one competitors_near_max segment. Needs location data access; unscored properties go last."},"gap_segment":{"type":"string","enum":["gym","burger","fast_food","coffee","bakery","pharmacy","supermarket","fashion","pizza"],"description":"The business kind the supply_gap sort counts."},"gap_radius_m":{"type":"integer","enum":[300,600],"description":"Radius in metres in which the supply_gap sort counts similar places: 600 (default) or 300 (about a 5-minute walk). Only with sort supply_gap."}}}}}}}}}},"/v1/plots/search":{"post":{"operationId":"search_plots","summary":"Search commercial plots (Germany)","description":"Find plots of land for sale or rent in Germany for a commercial building, from Casafari's property graph. Plots only, never premises: counts and results come from a separate set, one result per plot however many agencies advertise it (the others in also_listed_by). Criteria are data: Länder (regions), municipalities, postcodes, plot type, operation, plot area, sale price and price per m², keywords in the property's own words, and `commercial_use`, how far the property's own text says a commercial building can go on the plot. Levels: zoned_commercial (GE, GI, MK, MU stated), zoned_mixed_or_special (MI, SO, MD stated: check the plan), commercial_use_stated (commercial use stated as allowed or suitable, no class: read the quote), building_land_use_not_stated, residential_only_stated, zoned_leisure_special (SO for recreation), not_building_land_stated, not_stated. The default is the first three; send \"all\" or any list to widen it. Each result gives its level with the quote it rests on and, for a stated class, zoning_source (a Flächennutzungsplan is not binding), the facts read from the text (zoning class, serviced, B-Plan, §34/§35, building permit, GRZ, GFZ), an excerpt and the agency's link. The level is what the property's text says, not a zoning check; coordinates are approximate.","responses":{"200":{"description":"Search commercial plots (Germany)","content":{"application/json":{"example":{"scope":"plots","country":"de","count":1,"returned":1,"offset":0,"criteria":{"regions":["bayern"],"plot_area_min":2000},"note":"Plots only, never premises.","results":[{"id":"pm_Qw7rT2xLmN8bV4cZ1aYs0e","title":"Gewerbegrundstück im Gewerbegebiet Nord","plot_type":"building_plot","country":"de","region":"Bayern","municipality":"Ingolstadt","zipcode":"85055","location_precision":"approximate","coordinates":{"lat":48.79,"lon":11.45,"precision":"approximate"},"for_sale":true,"for_rent":false,"sale_eur":1200000,"rent_eur_month":null,"plot_area_m2":6000,"sale_eur_per_m2":200,"commercial_use":{"level":"zoned_commercial","meaning":"The plot's text states a commercial zoning class: GE, GI, MK or MU (Gewerbe-, Industrie-, Kerngebiet, urbanes Gebiet).","evidence":"Das Grundstück liegt im Gewerbegebiet (GE)","facts_read":true},"facts_from_text":{"zoning_class":"GE","serviced":true},"excerpt":"Voll erschlossenes Gewerbegrundstück, ca. 6.000 m², direkte Anbindung an die A9.","agency":{"name":"Muster Immobilien","listing_url":"https://muster-immobilien.de/expose/1"},"agency_links":[{"name":"Muster Immobilien","listing_url":"https://muster-immobilien.de/expose/1"}]}]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"criteria":{"type":"object","additionalProperties":false,"properties":{"regions":{"type":"array","items":{"type":"string"},"description":"Länder by name or slug: \"Bayern\", \"nordrhein-westfalen\"."},"municipalities":{"type":"array","items":{"type":"string"},"description":"Towns or cities as the property's data names them: \"München\", \"Leipzig\"."},"zipcodes":{"type":"array","items":{"type":"string"},"description":"Postcodes or their first digits: \"80331\", \"04\"."},"plot_types":{"type":"array","items":{"type":"string","enum":["building_plot","rural_plot"]},"description":"building_plot (Grundstück) or rural_plot (agricultural, forest and other land)."},"operation":{"type":"string","enum":["sale","rent","either"]},"plot_area_min":{"type":"number","description":"m²; a plot that states no area is out."},"plot_area_max":{"type":"number"},"sale_price_min":{"type":"number","description":"EUR total."},"sale_price_max":{"type":"number"},"sale_price_m2_max":{"type":"number","description":"EUR per m² of plot area."},"commercial_use":{"oneOf":[{"type":"string","enum":["all"]},{"type":"array","items":{"type":"string","enum":["zoned_commercial","zoned_mixed_or_special","commercial_use_stated","building_land_use_not_stated","residential_only_stated","zoned_leisure_special","not_building_land_stated","not_stated"]}}],"description":"Levels to keep; default zoned_commercial, zoned_mixed_or_special, commercial_use_stated."},"serviced":{"type":"boolean","description":"true: drop plots whose text says they are not serviced (unerschlossen); plots that do not say stay."},"keywords":{"type":"array","items":{"type":"string"},"description":"Words or phrases the property's text must contain, all of them: \"Gleisanschluss\", \"Autobahn\"."}}},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20},"offset":{"type":"integer","minimum":0,"default":0,"description":"Results to skip, for the next page."},"sort":{"type":"string","enum":["commercial_use","newest","price_asc","area_desc","price_m2_asc"],"default":"commercial_use"}}}}}}}},"/v1/plots/{id}":{"get":{"operationId":"get_plot","summary":"Get one plot","description":"One plot in full by the id search_plots returned: its data, commercial-use level, the facts read from its text with the quote each came from (fact_sources), an excerpt, the agency's link and the other agencies advertising it (also_listed_by).","responses":{"200":{"description":"Get one plot","content":{"application/json":{"example":{"id":"pm_Qw7rT2xLmN8bV4cZ1aYs0e","title":"Gewerbegrundstück im Gewerbegebiet Nord","plot_type":"building_plot","country":"de","region":"Bayern","municipality":"Ingolstadt","zipcode":"85055","location_precision":"approximate","coordinates":{"lat":48.79,"lon":11.45,"precision":"approximate"},"for_sale":true,"for_rent":false,"sale_eur":1200000,"rent_eur_month":null,"plot_area_m2":6000,"sale_eur_per_m2":200,"commercial_use":{"level":"zoned_commercial","meaning":"The plot's text states a commercial zoning class: GE, GI, MK or MU (Gewerbe-, Industrie-, Kerngebiet, urbanes Gebiet).","evidence":"Das Grundstück liegt im Gewerbegebiet (GE)","facts_read":true},"facts_from_text":{"zoning_class":"GE","serviced":true},"excerpt":"Voll erschlossenes Gewerbegrundstück, ca. 6.000 m², direkte Anbindung an die A9.","agency":{"name":"Muster Immobilien","listing_url":"https://muster-immobilien.de/expose/1"},"agency_links":[{"name":"Muster Immobilien","listing_url":"https://muster-immobilien.de/expose/1"}],"fact_sources":{"zoning_class":"Das Grundstück liegt im Gewerbegebiet (GE)","serviced":"voll erschlossen"}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/brief/file":{"post":{"operationId":"brief_file","summary":"Read a brief from a file","description":"The premises requirements a file states: a site brief, a location profile or a requirements sheet, as a PDF, a photo or scan (JPG, PNG, WebP, HEIC), a Word, Excel or PowerPoint file (or OpenDocument), or text. Each requirement keeps the file's own words as `quote`; where the text can be read here (Office and text files) a requirement whose quote is not in it is dropped, and `quotes_checked` is true. For PDFs and images it is false. `brief` is the requirements joined in plain words, ready for POST /v1/search after the customer has checked it. Nothing is searched here. Multipart, the file in the field `file`, up to 10 MB (413 above that). Accepted: .pdf,.jpg,.jpeg,.png,.webp,.heic,.heif,.txt,.md,.csv,.tsv,.html,.htm,.rtf,.json,.xml,.docx,.xlsx,.pptx,.odt,.ods,.odp. Counted against the account's daily calls like a search. The file is not stored. Over MCP (no multipart), the tool `brief_from_file` takes the file as JSON: `{\"content_base64\": \"TG9jYWwgZW4gTWFkcmlk…\", \"media_type\": \"text/plain\", \"filename\": \"perfil.txt\"}`, with the same limits, checks and answer.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"The brief the file states","content":{"application/json":{"schema":{"type":"object","required":["brief","requirements","quotes_checked"],"properties":{"brief":{"type":"string","description":"The requirements in plain words, joined with '; ' (at most 1,500 characters)."},"requirements":{"type":"array","maxItems":30,"items":{"type":"object","required":["requirement","quote"],"properties":{"requirement":{"type":"string"},"quote":{"type":"string","description":"The file's own words that state it."}}}},"quotes_checked":{"type":"boolean","description":"True when each quote was checked against the file's text (Office and text files)."}}},"example":{"brief":"Madrid; rent; 120-250 m²; smoke extraction","requirements":[{"requirement":"Madrid","quote":"Local en Madrid"},{"requirement":"rent","quote":"en alquiler"},{"requirement":"120-250 m²","quote":"120-250 m²"},{"requirement":"smoke extraction","quote":"salida de humos"}],"quotes_checked":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"File larger than the limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/health":{"get":{"operationId":"health","summary":"Service status and data vintages","description":"No key needed. The version, the vintages of the location data (Targomo datasets, Overture Maps places release), when the sync last updated a property, and how many properties are active. Cached for 60 seconds. 503 with ok false when the database cannot be read.","security":[],"responses":{"200":{"description":"Status","content":{"application/json":{"example":{"ok":true,"version":"1.0.0","data":{"targomo":[{"dataset":"Footfall estimates","vintage":"2024"},{"dataset":"MB Research sociodemographics","vintage":"2024"}],"overture_release":"2026-09-23.1","last_sync_at":"2026-10-15T03:12:00Z","active_listings":41250},"checked_at":"2026-10-15T09:00:00.000Z"}}}},"503":{"description":"Database unreadable; ok is false and the data fields are null"}}}},"/v1/tools":{"get":{"operationId":"tools","summary":"The operations and their input schemas","security":[],"responses":{"200":{"description":"Tools"}}}},"/v1/openapi.json":{"get":{"operationId":"openapi_json","summary":"This document","security":[],"responses":{"200":{"description":"OpenAPI 3.1"}}}},"/v1/admin/plan":{"post":{"operationId":"admin_plan","summary":"Run the sync plan now (admin accounts only)","responses":{"200":{"description":"Plan result"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/requeue":{"post":{"operationId":"admin_requeue","summary":"Send chosen premises back through the sync (admin accounts only)","responses":{"200":{"description":"How many were queued"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/places":{"post":{"operationId":"admin_places","summary":"Load Overture Maps places, 1,000 a call, or prune old releases with {\"prune_before\": \"<release>\", \"dry_run\": true} (admin accounts only; a dry run unless dry_run is false)","responses":{"200":{"description":"How many were written"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/snapshot":{"post":{"operationId":"admin_snapshot","summary":"Write the market snapshot of one day (admin accounts only)","description":"?day=YYYY-MM-DD (UTC), default yesterday. Per province, town (5+ active units), type and operation: units on the market, properties first seen and withdrawn that day, and the quartiles of the asking price per m². The nightly cron runs it before the sync plan.","responses":{"200":{"description":"The day and how many rows were written"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/keys":{"post":{"operationId":"post_admin_keys","summary":"Create an API key for a client (admin accounts only)","description":"Returns the secret key (pk_...) once, in this response only; only its SHA-256 is stored. Hand it to the client through a channel meant for secrets.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["client"],"properties":{"client":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{1,40}$"},"label":{"type":"string","maxLength":200}}}}}},"responses":{"200":{"description":"The key, its hash, client, label and created_at"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"get_admin_keys","summary":"List a client's keys: hash, label, created date, disabled (admin accounts only; never the secrets)","parameters":[{"name":"client","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The client's keys"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/keys/{hash}":{"delete":{"operationId":"delete_admin_keys_hash","summary":"Revoke a key by its hash (admin accounts only); it stops working within a minute","parameters":[{"name":"hash","in":"path","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{64}$"}}],"responses":{"200":{"description":"The key, now disabled"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No key with that hash"},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/accounts/{client}":{"get":{"operationId":"get_admin_accounts_client","summary":"An account's plan fields, location access (never the subkey) and effective limits (admin accounts only)","parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{1,40}$"}}],"responses":{"200":{"description":"The account"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No account with that client"},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"put_admin_accounts_client","summary":"Set an account's name, plan fields and location access (admin accounts only)","description":"Merges the fields sent; null removes one. minute_limit is one of 10, 30, 60, 120, 300 (default 60). max_results is at most 200 (default 200). live_location_points_daily caps live explain_location points a day (unset: no quota); beyond it the call answers 429 quota_reached. location is \"owner\", {\"subkey\": \"...\"} (stored encrypted, never returned) or null. admin cannot be set here.","parameters":[{"name":"client","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{1,40}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":["string","null"],"maxLength":200},"daily_limit":{"type":["integer","null"],"minimum":1},"minute_limit":{"type":["integer","null"],"enum":[10,30,60,120,300,null]},"max_results":{"type":["integer","null"],"minimum":1,"maximum":200},"live_location_points_daily":{"type":["integer","null"],"minimum":0},"location":{"oneOf":[{"const":"owner"},{"type":"object","required":["subkey"],"properties":{"subkey":{"type":"string"}}},{"type":"null"}]}}}}}},"responses":{"200":{"description":"The account, as GET returns it"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/assessments":{"post":{"operationId":"admin_assessments","summary":"Site assessments for chosen premises through the Gemini Batch API (admin accounts only)","description":"{\"ids\": [\"pm_...\"] (1 to 50), \"segments\"?: [...], \"force\"?: true}. Builds each premises' fact sheet with this account's location access, skips those already assessed for the same inputs unless force, and submits one batch job; the 10-minute tick stores the checked answers, which get_premises then returns. For shortlists, evals and re-reads; never a pass over all properties.","responses":{"200":{"description":"The batch job, how many were submitted, already current or not found"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/stores":{"put":{"operationId":"stores","summary":"Your own stores, for \"not within N m of our stores\" (own_stores_away_m)","description":"PUT replaces the list: text/csv with a header naming name, lat and lon (latitude/longitude also work; comma, semicolon or tab separated), or JSON {\"stores\": [{\"name\", \"lat\", \"lon\"}]}. Up to 5,000 stores, in Spain, coordinates only (no addresses); the body under 1 MB. GET returns the list; DELETE removes it. Only your account's searches read it.","requestBody":{"required":true,"description":"The whole list, replacing the one stored. Each store needs a name and its coordinates in Spain (the Canaries, Ceuta and Melilla included); a point outside is refused, usually lat and lon swapped.","content":{"application/json":{"schema":{"type":"object","required":["stores"],"properties":{"stores":{"type":"array","minItems":1,"maxItems":5000,"items":{"type":"object","required":["name","lat","lon"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Named in the own_stores_within_Nm verdict's evidence (nearest store and distance); cut at 120 characters."},"lat":{"type":"number","minimum":27.4,"maximum":44,"description":"Latitude, decimal degrees (a numeric string with a decimal comma is read too)."},"lon":{"type":"number","minimum":-18.4,"maximum":4.6,"description":"Longitude, decimal degrees (a numeric string with a decimal comma is read too)."}}}}}},"example":{"stores":[{"name":"Gran Vía 28","lat":40.42,"lon":-3.7051},{"name":"Diagonal 471","lat":41.3942,"lon":2.1457}]}},"text/csv":{"schema":{"type":"string","description":"A header row naming name (or store), lat (or latitude) and lon (or lng, longitude), then one store a line. Comma, semicolon or tab separated; quoted fields may hold the separator."},"example":"name,lat,lon\nGran Vía 28,40.42,-3.7051\nDiagonal 471,41.3942,2.1457\n"}}},"responses":{"200":{"description":"How many stores are stored and when the list was written","content":{"application/json":{"schema":{"type":"object","required":["count","updated_at"],"properties":{"count":{"type":"integer","minimum":1,"maximum":5000,"description":"Stores in the list now."},"updated_at":{"type":"string","format":"date-time","description":"When this list replaced the previous one (UTC)."}}},"example":{"count":2,"updated_at":"2026-10-15T09:00:00.000Z"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Body over 1 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/embed/search":{"post":{"operationId":"embed_search","summary":"Search from the embeddable box (/embed.js)","description":"Publishable key (pub_...) in the body; works only from the origins the key was issued for. Send Content-Type text/plain.","security":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"object","required":["key"],"properties":{"key":{"type":"string"},"brief":{"type":"string"},"limit":{"type":"integer","minimum":1,"maximum":10}}}}}},"responses":{"200":{"description":"Counts and trimmed results"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/embed/premises":{"post":{"operationId":"embed_premises","summary":"One premises from the embeddable box","security":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"object","required":["key","id"],"properties":{"key":{"type":"string"},"id":{"type":"string"}}}}}},"responses":{"200":{"description":"Trimmed premises"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"No access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}