# Cenogram API > Property and parcel intelligence for Poland, built on 8M+ transactions from the national price > registry (Rejestr Cen Nieruchomości, RCN). These are prices recorded in notarial deeds, not asking > prices from listings. Coverage is nationwide, from 2003 to the present, refreshed roughly every two > weeks. On top of prices: the cadastral parcel, the deed history recorded against it, and context > layers drawn from official public registers. Base URL: https://cenogram.pl/api/v1/ The unversioned https://cenogram.pl/api/ still serves as an alias, but new integrations should use /api/v1/. ## Authentication Send an API key as either header: X-Api-Key: Authorization: Bearer OAuth 2.1 with dynamic client registration is also supported, and is what the hosted MCP server uses. Get a key at https://cenogram.pl/api - a new account starts with a token allowance and a trial. The current allowances, trial length and prices are on that page; they are not repeated here, because a figure copied into this file would go stale on its own. ## Token metering Every call costs tokens. The price is per operation and is listed with each endpoint below; it is also machine-readable in the OpenAPI document, in the `x-cenogram-token-cost` extension field on every operation. Tokens and credits are the same unit under two names. The response headers say credits: X-Credits-Cost tokens charged for this call X-Credits-Balance balance after the call X-Credits-Refunded tokens given back (see refund rules below) Discovery catalogs cost nothing, so an agent can browse what is covered before spending anything. When the balance runs out the API answers 402. The 402 body carries the current balance and, on a free account, the date the next allowance arrives - so a client can back off until then instead of retrying blindly. Paid plans raise the allowance. ## Refund rules You pay for answers, not for attempts. Anything that returns 4xx or 5xx is refunded automatically. Beyond that there are three families, and they differ on purpose - a checked negative is an answer, an unanswerable question is not. 1. Transaction-keyed layers (`/transactions/{id}/…`) Refunded when the answer is empty: the transaction has no linked parcel, or no linked parcel touches the layer. A malformed id stays charged. 2. Parcel layers (`/parcels/{key}`, `/parcels/{key}/…`) `covered` and `covered_no_data` are BOTH charged. On a parcel we hold and a layer we checked, "nothing here" is an informative negative and it is what you asked for. Refunded on `not_covered` (a well-formed cadastral id we do not hold) and on `not_computed` (a live computation that could not finish - retry later). 3. The composite report (`/parcels/{key}/report`) A threshold ladder, stated per response in `billing.rule`: a parcel that does not resolve is fully refunded; a parcel that resolves with at least one `covered` section is charged the full weight; a parcel that resolves with only `covered_no_data` sections is charged the core floor and the rest is refunded; a parcel whose every section is `not_computed` or `not_covered` is fully refunded. ## Response conventions - Field names are snake_case. This holds across REST and MCP. - Missing data is 200 plus a `coverage` field, not 404. 404 means the resource itself is unknown (an id that does not exist); it does not mean "we have nothing to say about it". Treat `coverage` as the answer to "did you look, and what did you find". - Per-parcel coverage is four-state: `covered`, `covered_no_data`, `not_covered`, `not_computed`. Statistical endpoints use their own canon instead: `full`, `low_sample`, `suppressed`, `no_data`. - Values carry `as_of` where freshness matters. Publication lag differs by county, so figures with different `as_of` are not directly comparable. - List endpoints are paginated and capped. `pagination.estimated` marks a count that is an estimate rather than an exact total. - Prices come from deeds. Do not mix them with asking prices and call the result a market rate. # Endpoints ## Transactions Search and filter transactions ### GET /api/v1/transactions - 2 tokens Search and filter real estate transactions. Optional: district, teryt, propertyType, marketType, dateFrom, dateTo, minPrice, maxPrice, minArea, maxArea, street, addressSource, buildingNumber, unitFunction, buildingType, mpzpDesignation, parcelId, bbox, transactionType, rooms, floor, floodRisk, heritageStatus, landslideRisk, ownershipType, landUse, buildingStoreys, minFootprintArea, maxFootprintArea, page, limit, sort, order ### GET /api/v1/transactions/{id}/permits - 4 tokens Returns the building-permit history for one transaction's parcels, from the national registry of positively resolved building permits and notifications (records since 2016): record kind (permit/notification), intent and works type, statutory object category, decision/intake dates, deciding authority, investment address… Required: id ### GET /api/v1/transactions/{id}/farmland - 4 tokens Returns the parcel-by-parcel agricultural land-eligibility breakdown for one transaction, derived from official nationwide agricultural land-eligibility data (updated weekly). Required: id ### GET /api/v1/transactions/{id}/planning - 4 tokens Returns the general-plan (plan ogólny) planning-zone breakdown for one transaction: for each linked parcel, the planning zones and overlay areas that touch it — zone symbol and name, share of the parcel covered, and the building parameters the plan sets (max building height, max development intensity, max built-up… Required: id ### GET /api/v1/transactions/{id}/buildings - 4 tokens Returns the building-by-building breakdown for one transaction: footprint area, storeys, and estimated total floor area (footprint × storeys). Required: id ### GET /api/v1/transactions/{id}/flood - 4 tokens Returns the parcel-by-parcel flood-hazard breakdown for one transaction: worst category (high/medium/low), hazard type (river/coastal/infrastructure), share of the parcel in the zone, and the full per-scenario list (each with its return period, e.g. 1-in-100-year). Required: id ### GET /api/v1/transactions/{id}/heritage - 4 tokens Returns the parcel-by-parcel heritage-listing breakdown for one transaction: category ('listed' = an individually listed monument on/at the parcel, 'zone' = the parcel lies within a protected area such as a historic urban layout, monument surroundings or a cultural landscape), share of the parcel inside protected… Required: id ### GET /api/v1/transactions/{id}/landslide - 4 tokens Returns the parcel-by-parcel landslide-hazard breakdown for one transaction: worst category ('landslide' = a mapped landslide area, 'threatened' = an area threatened by mass movements), share of the parcel inside the mapped zones, and the per-zone list (each with its source_version_date — the source-record version… Required: id ### GET /api/v1/transactions/{id}/nature - 4 tokens Returns the parcel-by-parcel nature breakdown for one transaction: for each linked plot with a nature signal — the nearest forest within 2 km (forest_distance_m, 0 = the plot overlaps forest) and its overlap share; and the overlapping nature-protection forms — the sharpest form's rank (protection_rank 1 = national park… Required: id ### GET /api/v1/transactions/{id}/subsurface - 4 tokens Returns the parcel-by-parcel subsurface breakdown for one transaction across two dimensions: mining terrains (mining_status 'active'|'former', mineral_class 'subsidence'|'surface'|'fluid'|'other' — the deformation-risk classification) and major groundwater reservoirs (groundwater_status 'documented'|'undocumented'). Required: id ### GET /api/v1/transactions/{id}/surroundings - 4 tokens Returns the parcel-by-parcel surroundings breakdown for one transaction: distance in metres from the parcel boundary to the nearest cemetery, landfill / waste-disposal site, sewage treatment plant, industrial-warehouse area, large industrial plant, and intensive livestock farm, derived from reference land-use and… Required: id ### GET /api/v1/transactions/{id}/transit - 4 tokens Returns the parcel-by-parcel public transport access breakdown for one transaction: nearest rail, metro, tram and bus stop distance (metres) and name, from open GTFS feeds. Required: id ### GET /api/v1/transactions/{id}/roads - 4 tokens Returns the parcel-by-parcel road-access evidence for one transaction: distance in metres from the parcel boundary to the nearest public road (within 500 m), to the nearest road of any kind (within 500 m) and to the nearest motorway/expressway/dual-carriageway (within 3 km, a traffic-nuisance proxy), plus the estimated… Required: id ## Statistics Market statistics and price data ### GET /api/v1/valuations - 5 tokens Indicative **market-value estimate** for an apartment, derived from comparable registered transaction prices near a point. Optional: lat, lng, parcelId, area, rooms, market, includeComps ### GET /api/v1/transactions/summary - 1 token Returns aggregate statistics for filtered transactions: median price/m², average area, date range, and total count. Optional: district, teryt, propertyType, marketType, dateFrom, dateTo, minPrice, maxPrice, minArea, maxArea, street, addressSource, buildingNumber, unitFunction, buildingType, mpzpDesignation, parcelId, bbox, transactionType, rooms, floor, floodRisk, heritageStatus, landslideRisk, ownershipType, landUse, buildingStoreys, minFootprintArea, maxFootprintArea ### GET /api/v1/transactions/summary/compare - 5 tokens Compare summary statistics across 2-5 districts. Optional: district, teryt, propertyType, marketType, dateFrom, dateTo, minPrice, maxPrice, minArea, maxArea, street, addressSource, buildingNumber, unitFunction, buildingType, mpzpDesignation, parcelId, bbox, transactionType, rooms, floor, floodRisk, heritageStatus, landslideRisk, ownershipType, landUse, buildingStoreys, minFootprintArea, maxFootprintArea, districts, include ### GET /api/v1/stats - 1 token Returns aggregate market statistics: total transactions, coverage (counties/districts), date range, and top districts by transaction count. ### GET /api/v1/price-per-m2 - 1 token Returns median price per m² for each district, sorted by value. ### GET /api/v1/stats/price-histogram - 2 tokens Returns price distribution histogram with configurable bins and max value. Optional: bins, max ## Spatial Geographic and polygon search ### GET /api/v1/locations/bbox - 1 token Returns bounding box coordinates for a district or TERYT area. Optional: district, teryt ### GET /api/v1/transactions/map - 5 tokens Returns transactions as GeoJSON FeatureCollection for map display. Optional: bbox, limit, district, teryt, propertyType, marketType, dateFrom, dateTo, minPrice, maxPrice, minArea, maxArea, street, addressSource, unitFunction, buildingType, mpzpDesignation, transactionType, rooms, floor, ownershipType, landUse, buildingStoreys, minFootprintArea, maxFootprintArea ### POST /api/v1/transactions/spatial - 5 tokens Search transactions within a GeoJSON polygon. Body: JSON (see the OpenAPI document for its shape) ## Parcels Parcel-first lookup: resolve a cadastral identifier, read the parcel core, the deed history recorded against it, and per-parcel context layers (flood, zoning, permits, buildings, heritage, landslide, subsurface, surroundings, transit, road access, agricultural use). Works for any existing parcel, including parcels that have never been transacted. ### GET /api/v1/parcels/{key}/permits - 4 tokens Building-permit history for one cadastral parcel, from the national registry of positively resolved building permits and notifications (records since 2016): record kind (permit/notification), intent and works type, statutory object category, decision/intake dates, deciding authority, investment address and volume. Required: key ### GET /api/v1/parcels/{key}/farmland - 4 tokens Agricultural land-eligibility for one cadastral parcel, from official nationwide agricultural land-eligibility data (updated weekly): eligible_area_m2 (the eligible agricultural area in square metres), pct_of_parcel (that area as a percentage 0-100 of the parcel surface, or null when the surface is unknown) and… Required: key ### GET /api/v1/parcels/{key}/planning - 4 tokens General-plan (plan ogólny) planning zones for one cadastral parcel: the planning zones and overlay areas that touch it — zone symbol and name, share of the parcel covered, and the building parameters the plan sets (max building height, max development intensity, max built-up coverage, min biologically active area). Required: key ### GET /api/v1/parcels/{key}/buildings - 4 tokens The buildings that physically stand on one cadastral parcel, computed by intersecting the parcel outline with nationwide building footprints: footprint area, the share of each footprint that lies on this parcel, storeys, estimated total floor area (footprint × storeys), a neutral function category (with its public PKOB… Required: key ### GET /api/v1/parcels/{key}/flood - 4 tokens Flood-hazard for one cadastral parcel: worst category (high/medium/low), hazard type (river/coastal/infrastructure), share of the parcel in the mapped zone, distance to the nearest zone, and the full per-scenario list (each with its return period, e.g. 1-in-100-year). Required: key ### GET /api/v1/parcels/{key}/heritage - 4 tokens Heritage-listing status for one cadastral parcel: category ('listed' = an individually listed monument on/at the parcel, 'zone' = the parcel lies within a protected area such as a historic urban layout, monument surroundings or a cultural landscape), share of the parcel inside protected areas, and the matching register… Required: key ### GET /api/v1/parcels/{key}/landslide - 4 tokens Landslide-hazard for one cadastral parcel: worst category ('landslide' = a mapped landslide area, 'threatened' = an area threatened by mass movements), share of the parcel inside the mapped zones, and the per-zone list (each with its source_version_date — the source-record version date, not a survey date). Required: key ### GET /api/v1/parcels/{key}/nature - 4 tokens Nature signal for one cadastral parcel: forest_distance_m = the nearest forest within 2 km (0 = the parcel overlaps forest, with forest_overlap_pct); and the overlapping nature-protection forms — protection_rank (1 = national park, 2 = nature reserve, 3 = Natura 2000, 4 = landscape park, 5 = protected landscape, 6 =… Required: key ### GET /api/v1/parcels/{key}/subsurface - 4 tokens Subsurface constraints for one cadastral parcel across two dimensions: mining terrains (mining_status 'active'|'former', mineral_class 'subsidence'|'surface'|'fluid'|'other') and major groundwater reservoirs (groundwater_status 'documented'|'undocumented'), each with the share of the parcel inside the mapped objects… Required: key ### GET /api/v1/parcels/{key}/surroundings - 4 tokens Distances (metres) from the parcel boundary to the nearest cemetery, landfill / waste-disposal site, sewage treatment plant, industrial-warehouse area, large industrial plant, and intensive livestock farm, derived from reference land-use and environmental-registry data. Required: key ### GET /api/v1/parcels/{key}/transit - 4 tokens Nearest rail, metro, tram and bus stop distance (metres) and name for one cadastral parcel, from open GTFS feeds. Required: key ### GET /api/v1/parcels/search - 1 token Search parcels by ID prefix. Optional: q, limit ### GET /api/v1/parcels/{key} - 1 token Look up one cadastral parcel by its public key: the EGiB id in URL-safe DASH form (`020302_2.0002.369-14` — the stored `/` replaced by `-` in the trailing number segment) or the internal UUID from /parcels/search. Required: key ### GET /api/v1/parcels/{key}/transactions - 4 tokens All RCN transactions recorded on one cadastral parcel (reverse of the transaction→parcel link), newest first, paginated. Required: key Optional: page, limit ### GET /api/v1/parcels/resolve - 1 token Resolve a parcel to its cadastral identity via exactly ONE of: `parcelId=` (full EGiB id — raw `/` or URL-safe `-` — or the internal UUID), `q=` (a full id, a UUID, or a free-text 'locality name + parcel number', e.g. `Sabnie 342/5`), or `lat=`&`lng=` (WGS84 point inside the parcel). Optional: q, parcelId, lat, lng ### GET /api/v1/parcels/{key}/report - 35 tokens One composite dossier for a cadastral parcel: the parcel core, all 13 enrichment layers (flood, heritage, landslide, subsurface, surroundings, transit, planning, buildings, permits, farmland, land_class — the official land-use & soil-quality classification and its re-designation consequences, where the county publishes… Required: key ## Locations District and location discovery ### GET /api/v1/districts - 1 token Returns all unique district names. Optional: q ### GET /api/v1/locations - free Browse administrative hierarchy: voivodeships → counties → municipalities → precincts. Optional: parent ## Demographics Demographic and economic indicators from GUS BDL (Central Statistical Office) ### GET /api/v1/demographics - 1 token Returns demographic, economic, housing, planning and other indicators from GUS BDL (Bank Danych Lokalnych / Central Statistical Office) for a TERYT administrative unit. Optional: location, teryt, year, yearFrom, yearTo, category ## Infrastructure Upcoming-infrastructure signals per municipality: public tenders, sewage-programme agglomerations, planned capital expenditure ### GET /api/v1/infrastructure-signals - 1 token Signals that a municipality is about to build infrastructure: public tenders for sewerage, water supply, roads, lighting, gas and cycling infrastructure; membership in a national sewage-treatment agglomeration; and the municipality's own planned capital expenditure. Optional: location, teryt ## Full specification - OpenAPI 3.1 document: https://cenogram.pl/api/docs/json - Interactive documentation: https://cenogram.pl/api/docs (renders in a browser - fetching it with a script returns an empty application shell, use the JSON above instead) - Get an API key and see plans: https://cenogram.pl/api ## MCP The same data is available to AI assistants over the Model Context Protocol, with its own tool names and the same token metering. - Setup instructions: https://cenogram.pl/en/mcp (Polish: https://cenogram.pl/mcp) - Streamable HTTP endpoint: https://mcp.cenogram.pl/mcp - Local stdio server: npx @cenogram/mcp-server - Authentication: API key or OAuth 2.1 with dynamic client registration