Cenogram Demographics API

Demographic and economic indicators from GUS BDL (Central Statistical Office)

Operations 1

GET /api/v1/demographics Demographic and economic indicators by location #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/cenogram-pl:cenogram-pl-demographics-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

cenogram-pl-demographics-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Cenogram Demographics API
  version: 1.0.0
  description: 'Property and parcel intelligence for Poland. 8M+ verified transactions from the official RCN registry (Rejestr Cen Nieruchomości) — prices from notarial deeds, not asking/listing prices, from 2003 to present, nationwide. On top of prices: the picture we hold of a parcel — cadastral core, the deed history recorded against it, and context layers (flood hazard, general-plan zoning, building permits, structures, heritage, landslide hazard, subsurface constraints from mining terrains and groundwater reservoirs, surroundings, transit access, road access, agricultural use), plus municipality-level demographics and infrastructure signals, and a comparable-based valuation estimate. Context layers are sourced from official public registers. Transaction coverage is nationwide; the cadastral parcel corpus is near-complete but not the whole register and not live — every parcel collection carries a `corpus_coverage` block measuring what we hold for the counties it addresses. Access is metered in tokens: a new account starts with a token allowance and a trial, after which a free account keeps calling on a recurring free allowance, and paid plans raise it. Current allowances, trial length and prices live at https://cenogram.pl/api and are deliberately not repeated here, because a figure frozen into this description goes stale on its own. A 402 response carries the current balance and, on a free account, the date the next tokens arrive. Every operation states its price both in prose and machine-readably, in the `x-cenogram-token-cost` extension field, generated from the one pricing table. Tokens and credits are the same unit under two names: the response headers (`X-Credits-Cost`, `X-Credits-Balance`, `X-Credits-Refunded`) and some older endpoint descriptions say credits. Working with an AI assistant? Give it https://cenogram.pl/api/llms.txt — this whole surface as one plain-text file, costs, refund rules and response conventions included.'
servers:
- url: https://cenogram.pl
security:
- apiKey: []
tags:
- name: Demographics
  description: Demographic and economic indicators from GUS BDL (Central Statistical Office)
paths:
  /api/v1/demographics:
    get:
      summary: Demographic and economic indicators by location
      tags:
      - Demographics
      description: 'Returns demographic, economic, housing, planning and other indicators from GUS BDL (Bank Danych Lokalnych / Central Statistical Office) for a TERYT administrative unit.


        **TERYT level detection** (auto from code length): 2 digits = voivodeship (e.g. `14` Mazowieckie), 4 digits = county (e.g. `1465` Warszawa), 6 digits = municipality auto-resolved to its 7-digit form (e.g. `146501` → `1465011` Warszawa, `146510` → `1465108` Śródmieście), 7 digits = municipality addressed directly.


        **The 7th digit is the TERYT unit type and it selects a different unit, not a spelling variant**: `1` urban gmina, `2` rural gmina, `3` urban-rural gmina as a whole, `4` / `5` the urban / rural part of an urban-rural gmina, `8` a district (dzielnica) of Warszawa. So `1465011` is Warszawa as one gmina, while its 18 districts are `1465028` (Bemowo) … `1465198` (Żoliborz), e.g. `1465108` Śródmieście. Pass the `…8` code for district-level indicators — the whole-gmina code returns city-wide figures. Likewise `…4` / `…5` split an urban-rural gmina into its town and its countryside, which the `…3` aggregate averages together.


        **Hierarchy**: response always includes data from the requested level + all parent levels. A gmina query returns gmina + powiat + podregion (NUTS3) + województwo indicators.


        **50 raw variables + 5 derived metrics** across 11 categories.


        **Indicators by level**: L6 gmina has the richest dataset (~44 indicators: demographics, economy, housing, planning, infrastructure, environment, education). L5 powiat adds safety, re_market (~21 indicators). L4 podregion NUTS3 has economy_macro (GDP). L2 województwo has economy_macro + prices (~6 indicators).


        **Derived metrics** (computed from raw variables): higher_education_pct, avg_new_apartment_size, developer_share_pct, residential_zoning_total_pct, property_crime_share_pct.


        **Time series**: use yearFrom/yearTo for multi-year data. Each indicator returns values as year-keyed object. Without year params, returns latest available year per variable.


        **Data freshness**: GUS BDL updates ~quarterly. Data cached for 24h. Census 2021 snapshot variables (education) update ~every 10 years.


        Costs 1 token per call.'
      parameters:
      - schema:
          type: string
          example: Warszawa
        in: query
        name: location
        required: false
        description: City, county or gmina name. A city/county name resolves to a 4-digit county TERYT (powiat level); a gmina name resolves to that gmina (richer L6 indicators); a name shared by several units answers 400 with the candidates and their codes. Use this OR teryt. teryt wins when both are given.
      - schema:
          type: string
          example: '1465011'
        in: query
        name: teryt
        required: false
        description: 'TERYT administrative code. Length determines level: 2 = voivodeship (e.g. 14), 4 = county (e.g. 1465), 6 or 7 = municipality (e.g. 146501, 1465011). In a 7-digit code the last digit is the TERYT unit type and picks a different unit: 1 urban, 2 rural, 3 urban-rural as a whole, 4/5 its urban/rural part, 8 a Warszawa district — so 1465011 is all of Warszawa and 1465108 is its Śródmieście district. Wins over location. Full list: https://eteryt.stat.gov.pl/'
      - schema:
          type: string
        in: query
        name: year
        required: false
        description: Return data for a specific year only (2003-current). Cannot be combined with yearFrom/yearTo.
      - schema:
          type: string
        in: query
        name: yearFrom
        required: false
        description: Start of year range for time series (min 2003). Use with yearTo for a closed range, or alone for open-ended (all years from N).
      - schema:
          type: string
        in: query
        name: yearTo
        required: false
        description: End of year range for time series (max current year + 1). Use with yearFrom for a closed range, or alone for open-ended (all years up to N).
      - schema:
          type: string
          example: demographics,economy,economy_macro,housing,planning,infrastructure,environment,safety,re_market,education,prices
        in: query
        name: category
        required: false
        description: 'Filter indicators by category (comma-separated). Without this param, all available categories are returned. Valid: demographics, economy, economy_macro, housing, planning, infrastructure, environment, safety, re_market, education, prices'
      x-cenogram-token-cost: 1
      responses:
        '200':
          description: Demographic indicators for the requested location
          content:
            application/json:
              schema:
                type: object
                description: Demographic indicators for the requested location
                properties:
                  location:
                    type: object
                    properties:
                      name:
                        type:
                        - 'null'
                        - string
                        description: Location name from GUS (null when coverage is no_data)
                      country_code:
                        type: string
                        description: ISO 3166-1 alpha-2 country code. Always 'PL'.
                      location_type:
                        type: string
                        enum:
                        - city
                        - county
                        - municipality
                        - voivodeship
                        description: city = miasto na prawach powiatu; county = powiat ziemski; municipality = gmina; voivodeship = województwo
                      teryt:
                        type: string
                        description: TERYT code (7-digit for gmina, as resolved)
                      level:
                        type: string
                        enum:
                        - gmina
                        - powiat
                        - wojewodztwo
                        description: Administrative level (same values as indicators[].level)
                      hierarchy:
                        type: object
                        description: 'Parent administrative units (empty for województwo). Possible keys: powiat, podregion, wojewodztwo.'
                        propertyNames:
                          enum:
                          - powiat
                          - podregion
                          - wojewodztwo
                        additionalProperties:
                          type: object
                          properties:
                            teryt:
                              type:
                              - 'null'
                              - string
                            name:
                              type: string
                  coverage:
                    type: string
                    enum:
                    - full
                    - no_data
                    description: Data availability axis. 'full' = GUS data present; 'no_data' = the TERYT was addressed but GUS has no indicators for it (indicators is {}).
                  indicators:
                    type: object
                    description: Map of indicator slug → indicator data. Available slugs depend on TERYT level and category filter.
                    additionalProperties:
                      type: object
                      properties:
                        name:
                          type: string
                          description: Human-readable indicator name (Polish)
                        unit:
                          type: string
                          description: Measurement unit (%, zł, m², szt., ‰, tys., osoba, ha, lata)
                        variable_id:
                          type:
                          - 'null'
                          - integer
                          description: GUS BDL variable ID (null for derived metrics)
                        category:
                          type: string
                          enum:
                          - demographics
                          - economy
                          - economy_macro
                          - housing
                          - planning
                          - infrastructure
                          - environment
                          - safety
                          - re_market
                          - education
                          - prices
                        level:
                          type: string
                          enum:
                          - gmina
                          - powiat
                          - podregion
                          - wojewodztwo
                          description: Administrative level this data comes from
                        values:
                          type: object
                          description: Year → value map. Single entry for latest-year queries, multiple for time series (yearFrom/yearTo).
                          additionalProperties:
                            type: number
                        derived:
                          type: boolean
                          description: true if computed from other variables (not raw GUS data)
                        note:
                          type: string
                          description: Data quality note (e.g. structural zeros for MNPP cities)
                        snapshot:
                          type: boolean
                          description: true for Census 2021 data (next update ~2031)
                        snapshot_note:
                          type: string
                          description: Explanation of snapshot data source (e.g. 'Census 2021, next update ~2031')
                  meta:
                    type: object
                    properties:
                      variables_count:
                        type: integer
                        description: Number of indicators in this response
                      categories:
                        type: array
                        items:
                          type: string
                          enum:
                          - demographics
                          - economy
                          - economy_macro
                          - housing
                          - planning
                          - infrastructure
                          - environment
                          - safety
                          - re_market
                          - education
                          - prices
                        description: Categories present in the response
                      levels_included:
                        type: array
                        items:
                          type: string
                          enum:
                          - gmina
                          - powiat
                          - podregion
                          - wojewodztwo
                        description: Administrative levels with data in this response
                      data_source:
                        type: string
                        description: Always 'GUS BDL (Bank Danych Lokalnych)'
                      as_of:
                        type:
                        - 'null'
                        - string
                        description: Freshest data year across all indicators (e.g. '2024'); null when no data
                      notes:
                        type: array
                        items:
                          type: string
                        description: Resolution caveats (e.g. a district/delegatura TERYT narrowed to its parent county). Absent when there is nothing to note.
                  demo:
                    type: boolean
                    description: Present and true when in demo mode (limited indicators, no hierarchy)
        '400':
          description: Invalid input (bad TERYT format, invalid year, unknown category)
          content:
            application/json:
              schema:
                type: object
                description: Invalid input (bad TERYT format, invalid year, unknown category)
                properties:
                  error:
                    type: string
                  statusCode:
                    type: integer
                  message:
                    type: string
                  candidates:
                    type: array
                    description: Units whose name resembles the one asked for (at most 5), same row shape as /api/locations. Absent when none were found.
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                          description: TERYT code of the unit
                        name:
                          type: string
                        typeName:
                          type:
                          - 'null'
                          - string
                          description: Municipality type, null for the other levels
                        level:
                          type: string
                          enum:
                          - voivodeship
                          - county
                          - municipality
                          - precinct
                        parent_name:
                          type:
                          - 'null'
                          - string
                          description: Name of the unit one level up
                  hint:
                    type: string
                    description: How to use `candidates`. Present only together with them.
        '401':
          description: Anonymous access not allowed — pass an API key, sign in, or use demo=true
          content:
            application/json:
              schema:
                type: object
                description: Anonymous access not allowed — pass an API key, sign in, or use demo=true
                properties:
                  error:
                    type: string
                  message:
                    type: string
                  reason:
                    type: string
                  signup_url:
                    type: string
                  docs:
                    type: string
        '404':
          description: No data found for this TERYT code in GUS BDL
          content:
            application/json:
              schema:
                type: object
                description: No data found for this TERYT code in GUS BDL
                properties:
                  error:
                    type: string
                  statusCode:
                    type: integer
                  message:
                    type: string
                  candidates:
                    type: array
                    description: Units whose name resembles the one asked for (at most 5), same row shape as /api/locations. Absent when none were found.
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                          description: TERYT code of the unit
                        name:
                          type: string
                        typeName:
                          type:
                          - 'null'
                          - string
                          description: Municipality type, null for the other levels
                        level:
                          type: string
                          enum:
                          - voivodeship
                          - county
                          - municipality
                          - precinct
                        parent_name:
                          type:
                          - 'null'
                          - string
                          description: Name of the unit one level up
                  hint:
                    type: string
                    description: How to use `candidates`. Present only together with them.
      operationId: getApiV1Demographics
      x-operation-id-source: derived
components:
  securitySchemes:
    apiKey:
      type: apiKey
      name: X-Api-Key
      in: header