MapaDanych.pl

Maschinenlesbare Version: /de/dokumentacja/protokol.md

Protokół MapaDanych 0.1

Normatywny opis interfejsu między dostawcą danych a portalem. W razie sprzeczności z inną dokumentacją obowiązuje ten dokument oraz schematy maszynowe:

Przygotowanie danych krok po kroku (zwłaszcza dla agentów AI) opisuje poradnik dla agentów AI, przystępne wprowadzenie znajdziesz w przewodniku dla dostawców. Poprawne wzorce: manifest-complete.json, data-points.json.

Przegląd

Dostawca                             Portal MapaDanych                 Przeglądarka
────────                             ─────────────────                 ────────────
manifest.json  ◄── GET (cache 10 min) ── rejestr → katalog ──────────► /api/catalog
endpoint danych ◄── GET ?bbox&zoom&… ─── proxy + walidacja + cache ───► /api/data/{provider}/{dataset}
kafelki rastrowe ◄────────────────────────────────────────────────────── bezpośrednio z przeglądarki

Zasady ogólne

Manifest

Pole Wymagane Opis
protocol tak Wersja protokołu, np. "0.1"
provider.id tak Identyfikator; musi odpowiadać id w rejestrze portalu
provider.name tak Nazwa wyświetlana jako źródło
provider.description, homepage, logo, contact nie
provider.managedBy nie provider (domyślnie) / portal – manifest usługi publicznej utrzymuje portal MapaDanych
license nie { name, url?, attribution } – domyślna licencja wszystkich zbiorów
datasets[] tak 1–200 zbiorów danych o unikalnym id

Zbiór danych

Pole Wymagane Opis
id, title tak
description nie
category nie territory, nature, water, risks, energy, transport, society, economy, infrastructure, sample, other; inna wartość → Inne
tags, keywords nie Do wyszukiwania i dla przyszłego asystenta
useCases nie Cele, do których zbiór się nadaje: construction, housing, land-purchase, agriculture, investment…
coverage nie { bbox?, area?, minZoom?, maxZoom? } – poniżej minZoom portal nie wczytuje danych
temporal nie { updated?, frequency?, param? } – param = klucz parametru, którym wybiera się okres (zob. filtr czasowy)
license nie Nadpisuje licencję dostawcy
source tak Skąd pobierać dane (zob. niżej)
presentation tak Jak dane renderować (zob. niżej)
fields[] nie Opis właściwości obiektów: key, label, type, unit, decimals, description, primary
params[] nie Filtry dla użytkownika (zob. niżej)
cache nie { ttl?: sekundy, store?: boolean }
live nie { interval: sekundy } – dane na żywo: otwarta mapa sama odświeża zbiór (10 do 3600 s), zob. cache
detail nie { url } – szczegóły obiektu na żądanie po kliknięciu (rozkład jazdy, bogatszy opis, wyróżnienie na mapie), zob. szczegóły obiektu
profile nie Rodzaj zbioru ze wspólnym zachowaniem w portalu: transit_vehicles = bieżące pozycje pojazdów transportu publicznego, zob. transport

source

geojson – format natywny.

{ "type": "geojson", "url": "/data/kontenery", "mode": "bbox", "maxFeatures": 5000 }

raster – gotowe kafelki, przeglądarka wczytuje je bezpośrednio ze źródła.

{ "type": "raster", "tiles": ["https://…/{z}/{x}/{y}.png"], "tileSize": 256, "minZoom": 0, "maxZoom": 19 }

Szablony obsługują {z}/{x}/{y} oraz {bbox-epsg-3857} (WMS GetMap). Tylko https.

presentation

type Geometria Opcje
circle punkty color, radius, opacity, strokeColor, strokeWidth, label, cluster
heatmap punkty weight, radius, intensity, colors[], opacity
line linie color, width, opacity, dash[], label
fill powierzchnie color, opacity, outlineColor, outlineWidth, label
raster kafelki opacity
auto cokolwiek color

Wszystkie typy mają opcjonalną legend: [{ label, color }] (maks. 20 pozycji). Portal pokazuje ją w legendzie bezpośrednio na mapie i w wyborze warstw. Dla typów wektorowych potrafi wyprowadzić ją z kolorów, dla raster nie – kolory są zapieczone w obrazach kafelków, dlatego legendę rastra podaj ręcznie (np. przejmując ją z legendy usługi WMS / ArcGIS).

Kolor (color) to albo ciąg szesnastkowy, albo reguła według właściwości obiektu:

{ "field": "druh", "type": "categorical", "values": { "papier": "#2563eb" }, "default": "#64748b" }
{ "field": "hodnota", "type": "interpolate", "stops": [[0, "#f7fcb9"], [100, "#004529"]] }
{ "field": "hodnota", "type": "step", "default": "#eee", "stops": [[10, "#fc8"], [50, "#e34"]] }
{ "type": "trend" }

trend koloruje obiekty według tego, czy ich wartość w czasie rośnie, stoi w miejscu, czy maleje. Oblicza go portal z wykresu zmian dm.chart – zob. zmiany w czasie i trend.

Liczba (radius, width, weight) to liczba albo { "field", "type": "interpolate", "stops": [[wartość, liczba], …] }.

Etykieta (label): { field, minZoom?, color?, size? }.

params

Filtr, który użytkownik ustawia w portalu; portal przesyła go jako parametr zapytania key=value.

type Wartość w zapytaniu
enum key=a (z options)
multi-enum key=a,b,c
number key=42 (w zakresie min–max)
range key=od,do
boolean key=true / false
date key=2026-10-06
date-range key=2026-01-01,2026-12-31
text key=… (maks. 200 znaków)

Klucze bbox, zoom, limit, cursor, lang, protocol są zarezerwowane. Portal wysyła tylko zadeklarowane parametry, a ich wartości wcześniej sprawdza; niewypełniony parametr zastępuje wartością default.

Filtr czasowy

Dane w czasie (wypadki, pomiary, zdarzenia) mają jeden parametr okresu i odwołują się do niego z temporal.param. Portal nie pokazuje go wtedy wśród pozostałych filtrów, lecz jako oś czasu w oknie pod legendą: suwak okresu i wykres słupkowy według lat, na którym okres można wybrać kliknięciem lub przeciągnięciem. Wybrany okres widać też przy warstwie w legendzie.

{
  "protocol": "0.1",
  "provider": { "id": "miasto-przyklad", "name": "Miasto Przykład" },
  "license": { "name": "CC BY 4.0", "attribution": "© Miasto Przykład" },
  "datasets": [{
    "id": "nehody",
    "title": "Wypadki drogowe",
    "description": "Wypadki zarejestrowane przez policję według skutków.",
    "category": "transport",
    "keywords": ["wypadek", "wypadek drogowy", "bezpieczeństwo", "obrażenia", "skrzyżowanie"],
    "useCases": ["transport", "housing"],
    "coverage": { "bbox": [19.79, 49.97, 20.22, 50.13], "minZoom": 12 },
    "temporal": { "frequency": "co roku", "param": "obdobi" },
    "source": { "type": "geojson", "url": "https://data.miasto-przyklad.pl/mapadanych/wypadki", "mode": "bbox", "maxFeatures": 5000 },
    "presentation": {
      "type": "circle",
      "color": { "field": "nasledky", "type": "categorical", "values": { "obrażenia": "#dc2626", "szkoda materialna": "#facc15" }, "default": "#facc15" }
    },
    "fields": [
      { "key": "nasledky", "label": "Skutki", "type": "string", "primary": true },
      { "key": "datum", "label": "Data", "type": "date" }
    ],
    "params": [{ "key": "obdobi", "label": "Okres", "type": "range", "min": 2015, "max": 2025, "step": 1, "default": "2025,2025" }]
  }]
}

Wykres rysuje portal z dm.timeline w odpowiedzi (zob. odpowiedź z danymi). Przy wartościach w czasie, dla których liczba obiektów nie ma sensu (liczba ludności, cena), wyślij zamiast tego zbiorczy przebieg w dm.chart – portal pokaże go przy suwaku jako wykres liniowy, zob. zmiany w czasie i trend. Bez żadnego z nich zostanie tylko suwak okresu.

Zmiany w czasie i trend

Standardowy sposób prezentacji danych, których wartość przy obiekcie zmienia się w czasie – liczba mieszkańców gminy, cena, zmierzone stężenie, frekwencja odwiedzających. Zawsze, gdy dane mają taki szereg, wysyłaj go; portal sam narysuje z niego wykres i może według niego kolorować.

Trend opiera się na zmianie względnej, dlatego nadaje się dla wielkości dodatnich (liczby, ceny, stężenia). Wartości w okolicy zera, takie jak saldo migracji, koloruj przez interpolate, a zmiany pokazuj tylko wykresem.

{
  "protocol": "0.1",
  "provider": { "id": "wojewodztwo-przyklad", "name": "Województwo Przykład" },
  "license": { "name": "CC BY 4.0", "attribution": "© Województwo Przykład" },
  "datasets": [{
    "id": "vyvoj-obyvatel",
    "title": "Zmiany liczby mieszkańców gmin",
    "description": "Gdzie mieszkańców przybywa, a gdzie ubywa. Kolor według trendu w wybranym okresie, w szczegółach gminy wykres według lat.",
    "category": "society",
    "keywords": ["mieszkańcy", "ludność", "trend", "wzrost", "wyludnianie"],
    "useCases": ["housing", "public-administration"],
    "temporal": { "frequency": "co roku", "param": "obdobi" },
    "source": { "type": "geojson", "url": "https://data.wojewodztwo-przyklad.pl/mapadanych/mieszkancy" },
    "presentation": { "type": "circle", "color": { "type": "trend", "threshold": 0.5 }, "radius": 7 },
    "fields": [
      { "key": "nazev", "label": "Gmina", "type": "string", "primary": true },
      { "key": "obyvatel", "label": "Mieszkańcy na koniec okresu", "type": "integer" }
    ],
    "params": [{ "key": "obdobi", "label": "Okres", "type": "range", "min": 2015, "max": 2025, "step": 1, "default": "2015,2025" }]
  }]
}

Odpowiedź wysyła wtedy przy każdej gminie szereg za wszystkie lata, a wybrany okres w highlight, na przykład { "from": "2015", "to": "2025" }.

Zapytanie o dane

GET {source.url}?bbox=minLon,minLat,maxLon,maxLat&zoom=10&limit=5000&lang=pl&protocol=0.1[&cursor=…][&{params}]
Accept: application/geo+json, application/json
User-Agent: DatovaMapa/0.1 (+https://mapadanych.pl/dokumentacja/dla-dostawcow)

Odpowiedź z danymi

GeoJSON FeatureCollection (RFC 7946). Obsługiwane geometrie: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon. Obiekty z geometry: null są pomijane.

Opcjonalne rozszerzenia:

{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature", "id": 1, "geometry": {…}, "properties": {…},
    "dm": { "title": "…", "description": "…", "url": "https://…", "color": "#e11d48", "chart": {…} }
  }],
  "dm": { "generated": "2026-10-06T08:00:00Z", "ttl": 3600, "total": 1, "truncated": false, "next": "…", "notice": "…", "timeline": […] }
}
{
  "type": "FeatureCollection",
  "features": [],
  "dm": {
    "timeline": [
      { "period": "2024", "count": 2366, "values": { "obrażenia": 701, "szkoda materialna": 1665 } },
      { "period": "2025", "count": 1894, "values": { "obrażenia": 652, "szkoda materialna": 1242 } }
    ]
  }
}

Zbiorczy przebieg dla całego obszaru zamiast liczby obiektów (wybrany okres 2023–2025):

{
  "type": "FeatureCollection",
  "features": [],
  "dm": {
    "chart": {
      "label": "Liczba ludności Polski na 31 grudnia",
      "highlight": { "from": "2022", "to": "2025" },
      "points": [
        { "period": "2021", "value": 38036118 },
        { "period": "2022", "value": 37766327 },
        { "period": "2023", "value": 37636508 },
        { "period": "2024", "value": 37489087 },
        { "period": "2025", "value": 37350000 }
      ]
    }
  }
}

Obiekt z wykresem zmian w szczegółach:

{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "id": "1261011",
    "geometry": { "type": "Point", "coordinates": [19.9450, 50.0647] },
    "properties": { "nazev": "Kraków", "obyvatel": 806000 },
    "dm": {
      "chart": {
        "label": "Liczba mieszkańców na 31 grudnia",
        "points": [
          { "period": "2023", "value": 803300 },
          { "period": "2024", "value": 804900 },
          { "period": "2025", "value": 806000 }
        ]
      }
    }
  }]
}

Szczegóły obiektu

Zbiór może oferować szczegóły obiektu na żądanie: po kliknięciu obiektu portal pokazuje okno z właściwości, a pod nim uzupełnia szczegóły pobrane osobno. Przydają się przy bogatszej treści, która nie mieści się we właściwościach: rozkład jazdy pociągu, przebieg przejazdu, wyróżnienie trasy na mapie. Pole detail w zbiorze zawiera szablon adresu z symbolem {id}, za który portal podstawia id obiektu z danych (obiekty muszą więc mieć stabilne id). Adres jest https albo względny wobec manifestu; walidator zgłasza szablon bez {id} (detail_url_without_id) i schemat inny niż https (detail_url_not_https).

"detail": { "url": "https://data.example.cz/detail?id={id}" }

Odpowiedzią jest JSON FeatureDetail (title i generated są obowiązkowe, pozostałe pola opcjonalne):

Dopóki szczegóły są otwarte, mapa odświeża je z interwałem live.interval zbioru. Portal buforuje odpowiedzi według ttl i sprawdza ich schemat tak samo jak dane. Nieznane id dostawca zwraca jako 404.

{
  "title": "RJ 1000",
  "subtitle": "→ Praha-Zahradní Město · RegioJet a.s.",
  "badge": {
    "text": "RJ 1000",
    "color": "#0f766e"
  },
  "status": {
    "label": "+8 min",
    "tone": "warning"
  },
  "journey": {
    "calls": [
      {
        "name": "Ostrava hlavní nádraží",
        "departure": "2026-11-04T05:05:00+01:00",
        "scheduledDeparture": "2026-11-04T05:05:00+01:00",
        "platform": "2",
        "state": "passed"
      },
      {
        "name": "Pardubice hlavní nádraží",
        "arrival": "2026-11-04T07:30:00+01:00",
        "departure": "2026-11-04T07:38:00+01:00",
        "scheduledArrival": "2026-11-04T07:22:00+01:00",
        "scheduledDeparture": "2026-11-04T07:30:00+01:00",
        "platform": "3",
        "state": "current"
      }
    ]
  },
  "highlight": {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [
              15.77,
              50.03
            ],
            [
              14.43,
              50.08
            ],
            [
              14.6,
              50.07
            ]
          ]
        },
        "properties": {
          "role": "upcoming"
        }
      },
      {
        "type": "Feature",
        "geometry": {
          "type": "Point",
          "coordinates": [
            15.77,
            50.03
          ]
        },
        "properties": {
          "role": "current",
          "name": "Pardubice hlavní nádraží"
        }
      }
    ]
  },
  "color": "#0f766e",
  "generated": "2026-11-04T07:35:00Z",
  "ttl": 30
}

Pełny przykład: detail-jizda.json.

Transport

Zbiory z bieżącymi pozycjami pojazdów transportu publicznego (pociągi, autobusy, tramwaje, metro…) oznacz "profile": "transit_vehicles". Portal pokaże je wtedy we wspólnej warstwie „Transport na żywo”: wszystkie tym samym stylem (kształt według rodzaju, kolor według opóźnienia), z jedną legendą, filtrem według rodzaju transportu, opóźnienia i przewoźnika oraz z wyszukiwaniem kursu. Użytkownik wybiera więc rodzaj transportu, a nie źródło danych.

Zbiór z profilem musi mieć live, prezentację circle i obiekty jako punkty z feature.dm.transit. Walidator zgłasza brak live (transit_missing_live), inną prezentację (transit_not_circle), obiekt bez dm.transit (transit_missing_properties) i obiekt, który nie jest punktem (transit_not_point).

Pole dm.transit Wymagane Opis
mode tak rail, bus, tram, metro, trolleybus, ferry, funicular, other
label tak Oznaczenie, którego szukają ludzie: pociąg (R 1234), linia (188)
line nie Linia, gdy różni się od oznaczenia (S2)
headsign, operator nie Cel kursu, przewoźnik
delay_min nie Opóźnienie w pełnych minutach, ujemne = przed czasem
delay_band tak on_time do 4 min, minor 5 do 14, medium 15 do 29, major 30 do 59, extreme 60 i więcej, unknown bez danych
bearing nie Kierunek jazdy w stopniach od północy
trip_ref nie Stały klucz kursu (ten sam przy kolejnych odświeżeniach); taki sam jak id obiektu, jeśli zbiór oferuje szczegóły kursu
observed_at tak Kiedy zmierzono pozycję (ISO 8601)

Każdy pojazd ma być na mapie tylko raz. Gdy te same pojazdy zgłasza kilka źródeł, niech wydaje je tylko jeden zbiór. Właściwości w properties (opisy dla ludzi w języku kraju) pozostają, dm.transit to neutralna część dla portalu.

{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "id": "1234|20261104",
    "geometry": { "type": "Point", "coordinates": [14.4352, 50.0833] },
    "properties": { "vlak": "R 1234", "cil": "Brno hl.n.", "zpozdeni_min": 6 },
    "dm": {
      "transit": {
        "mode": "rail", "label": "R 1234", "headsign": "Brno hl.n.", "operator": "České dráhy",
        "delay_min": 6, "delay_band": "minor", "bearing": 135, "trip_ref": "1234|20261104",
        "observed_at": "2026-11-04T07:35:10Z"
      }
    }
  }]
}

Pełny przykład: data-doprava.json.

Cache

Walidacja

Zgodność z protokołem sprawdza walidator (POST /api/validate, test na żywo GET /api/validate?manifestUrl=… lub narzędzia MCP validate_manifest i validate_data). Rozróżnia:

Każde ustalenie ma stabilny code (przegląd kodów), ścieżkę path, a przy zaleceniach wskazówkę hint. Kody nie zmieniają się między wersjami minor, nowe mogą dochodzić.

Rozwój protokołu