---
title: "Nachhaltigkeits- und SDG-Indikatoren als Zeitreihe (Wegweiser, Tier A)"
method: GET
path: "/api/v1/cities/{slug}/sustainability"
tags: ["cities"]
---

# Nachhaltigkeits- und SDG-Indikatoren als Zeitreihe (Wegweiser, Tier A)

`GET /api/v1/cities/{slug}/sustainability`

Kommunale Nachhaltigkeits- und SDG-Indikatoren je Gemeinde aus dem Wegweiser Kommune der Bertelsmann Stiftung (CC0): Flächeninanspruchnahme, Naherholungsflächen, erneuerbare Energie im Wohnungsneubau, Breitbandversorgung, Beschäftigung, Bildung, soziale Teilhabe und weitere. Anders als /indicators (INKAR, jüngster Wert) trägt jeder Indikator hier die ganze ZEITREIHE, in der Regel 2006 bis 2023, dazu latest_year/latest_value für den jüngsten Punkt. Jahre ohne Wert fehlen in der Reihe (nie eine erfundene Null). 53 Indikatoren liegen erst ab Kreisebene vor und fehlen deshalb bei kreisangehörigen Städten. Toggle aus -> 200 source_status="disabled"; kein Snapshot -> 200 source_status="not_ingested".

## Path parameters

- `slug` string, required

## Response `200`

Zeitreihen-Envelope (CanonicalRecord mit IndicatorSeriesPayload) oder null.

- object
  - `data` CanonicalRecord, required
    - `city_slug` string, required
    - `schema_version` integer, required
    - `record_id` string, required — Deterministischer Primärschlüssel (computed, immer im Dump).
    - `content_hash` string, required — Deterministischer Dedup-Hash der Nutzdaten (computed, immer im Dump).
    - `ags` string, nullable — Amtlicher Gemeindeschlüssel als Join-Key (kein Pfadsegment).
    - `wikidata_qid` string, nullable — Wikidata-QID als Join-Key.
    - `geo` object, nullable
      - `lat` number
      - `lon` number
    - `observed_at` string, date-time, nullable
    - `retrieved_at` string, date-time, required
    - `source` 'wikidata' | 'dwd' | 'osm' | 'autobahn' | 'bnetza' | 'uba' | 'delfi' | 'hvv' | 'pegelonline' | 'hochwasser' | 'dwd_pollen' | 'genesis' | 'zensus' | 'mastr' | 'bkg' | 'bundeswahl' | 'divi' | 'feiertage' | 'berlin_viz' | 'hamburg_baustellen' | 'koeln_verkehr' | 'muenchen_baustellen' | 'dortmund_baustellen' | 'sperrinfosys' | 'mobidata_bw', required
    - `license_id` 'cc0' | 'cc_by_4_0' | 'dl_de_by_2_0' | 'dl_de_zero_2_0' | 'geonutzv' | 'odbl' | 'cc_by_sa_4_0' | 'unknown', required
    - `license_tier` 'A' | 'B' | 'C', required
    - `attribution` Attribution, required
      - `text` string, required
      - `license_url` string, nullable
      - `modified` boolean
    - `payload` union, required
      - CityBaseDataPayload
        - `kind` 'city_base', required
        - `population` integer, nullable
        - `area_km2` number, nullable
      - AirQualityPayload
        - `kind` 'air_quality', required
        - `station_id` string, nullable
        - `pm10` number, nullable
        - `no2` number, nullable
        - `pm25` number, nullable
        - `o3` number, nullable
        - `so2` number, nullable
      - WeatherPayload
        - `kind` 'weather', required
        - `station_id` string, nullable
        - `temperature_c` number, nullable
        - `humidity` number, nullable
        - `wind_speed` number, nullable
        - `condition` string, nullable
      - PoiPayload
        - `kind` 'poi', required
        - `poi_type` string, required
        - `count` integer, required
        - `total_available` integer, nullable
        - `truncated` boolean
        - `items` object[]
      - TrafficEventPayload
        - `kind` 'traffic_event', required
        - `station_id` string, nullable
        - `roadworks` object[]
        - `warnings` object[]
      - TransitStopPayload
        - `kind` 'transit_stop', required
        - `stop_id` string, required
        - `stop_name` string, required
        - `location_type` integer, nullable
        - `parent_station` string, nullable
        - `platform_code` string, nullable
        - `wheelchair_boarding` integer, nullable
      - ChargingStationPayload
        - `kind` 'charging_station', required
        - `count` integer, required
        - `stations` object[]
      - WaterLevelPayload
        - `kind` 'water_level', required
        - `station` string, nullable
        - `water` string, nullable
        - `value` number, nullable
        - `unit` string, nullable
      - FloodWarningPayload
        - `kind` 'flood_warning', required
        - `warnings` object[]
        - `stand` string, nullable
      - PollenUvPayload
        - `kind` 'pollen_uv', required
        - `region_id` integer, nullable
        - `region_name` string, nullable
        - `pollen` object
        - `uv_index` number, nullable
      - DemographicsPayload
        - `kind` 'demographics', required
        - `population` integer, nullable
        - `households` integer, nullable
        - `buildings` integer, nullable
        - `rent_avg` number, nullable
        - `reference_year` integer, nullable
        - `series` object[]
      - EnergyAssetPayload
        - `kind` 'energy_asset', required
        - `count` integer, required
        - `by_type` object
        - `assets` object[]
      - AdminBoundaryPayload
        - `kind` 'admin_boundary', required
        - `ags` string, nullable
        - `gen_name` string, nullable
        - `area_km2` number, nullable
        - `reference_year` integer, nullable
      - ElectionResultPayload
        - `kind` 'election_result', required
        - `election` string, nullable
        - `granularity` string
        - `area_name` string, nullable
        - `turnout` string, nullable — Wahlbeteiligung in Prozent als String mit Dezimal-Komma (kerg2, Zeile Gruppenname "Wählende", Spalte Prozent), z.B. "82,5122".
        - `results` object[]
      - HolidayPayload
        - `kind` 'holiday', required
        - `state` string, nullable
        - `year` integer, nullable
        - `holidays` object[]
        - `school_holidays` object[]
      - HospitalPayload
        - `kind` 'hospital', required
        - `count` integer, required
        - `hospitals` object[]
        - `reference_date` string, nullable
      - IcuCapacityPayload
        - `kind` 'icu_capacity', required
        - `kreis_id` string, nullable
        - `kreis_name` string, nullable
        - `beds_free` integer, nullable
        - `beds_occupied` integer, nullable
        - `hospitals` object[] — Klinikscharfe Live-Status-Einschätzungen (DIVI, Tier C) je Krankenhaus-Standort (bezeichnung, ort, letzte_meldung, status_high_care, status_ecmo). Die Live-API liefert keine numerische Belegung mehr (beds_free/beds_occupied bleiben null und tragen nur das Tier-A-Kreis-Aggregat).
        - `datum` string, nullable
      - RoadEventPayload
        - `kind` 'road_event', required
        - `city_source` string, nullable
        - `events` object[]
      - WebcamPayload
        - `kind` 'webcam', required
        - `count` integer, required
        - `webcams` object[]
  - `meta` Meta, required
    - `correlation_id` string, nullable
    - `source_status` 'ok' | 'no_data' | 'disabled' | 'not_ingested' | 'not_covered' — Ehrlicher Quellen-Status der Antwort. "ok" (Daten vorhanden), "no_data" (Quelle erreichbar/abgedeckt, aber gerade keine Daten), "disabled" (Quelle per Toggle aus), "not_ingested" (kein Snapshot), "not_covered" (Stadt ist für diesen teilabgedeckten Endpunkt strukturell nicht abgedeckt; data=null, siehe covered_cities). Klar unterscheidbar vom 404 (Stadt unbekannt).
    - `cache_status` string, nullable — Cache-Herkunft (hit/miss/stale), sofern die Route cacht.
    - `covered_cities` string[] — Nur bei source_status="not_covered": die Stadt-Slugs, die dieser teilabgedeckte Endpunkt tatsächlich bedient (z. B. flood, webcams, traffic, road-events).
    - `pagination` object — Bei paginierbaren Datenart-Listen (charging, energy, events, transit, OSM-Feature-Endpunkte): der EHRLICH ausgewiesene Ausschnitt (keine stille Kappung). KANAL-ABHÄNGIGER Default für gleiche URL: direktes REST liefert die volle Liste (limit=null, returned==total, truncated=false); GPT-Actions (erkannt am OpenAI-Header) bekommen ein serverseitig gebundenes Default-Limit; MCP-Aufrufe sind gebunden, weil der MCP-Client selbst ein Default-Limit setzt. Kanalunabhängige Overrides: limit=all (oder ?all=1) erzwingt die volle Liste, limit + offset blättern gezielt. meta.pagination ist bei ALLEN Kanälen gesetzt.
      - `total` integer — Gesamtzahl der Einträge (voller Bestand).
      - `returned` integer — Zahl der auf dieser Seite ausgelieferten Einträge.
      - `limit` integer, nullable — Angewandtes Seiten-Limit; null bei Vollausgabe (REST-Default oder limit=all).
      - `offset` integer — Start-Offset der Seite.
      - `truncated` boolean — true, wenn hinter dieser Seite noch Einträge liegen (offset + returned < total); bei Vollausgabe false.

## Other responses

- `404` — Unbekannte Stadt

## Changes

- **2026-07-31** `eeabcc0126fd` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/infranode/apis/infranode-api/changes/api/v1/cities/:slug/sustainability/get.md)

---

[API](https://skmtc.dev/infranode/apis/infranode-api.md) · [All operations](https://skmtc.dev/infranode/apis/infranode-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/infranode/infranode-api/revisions/eeabcc0126fd/schema)
