KOSAVA v7 OpenData
Agencija za zaštitu životne sredine SEPA — API Documentation
Portal omogućava pristup podacima o kvalitetu vazduha i meteorološkim parametrima iz mreža za praćenje. API je dostupan isključivo za čitanje: nema upisa podataka, nema autentikacije i nema ograničenja broja zahteva. Svi prikazani podaci pripadaju organizaciji naznačenoj na samom portalu.
Autentikacija
Ovaj API ne zahteva autentikaciju. Svi endpointi su javno dostupni. Nema API ključeva, tokena niti sesijskih kolačića. Jednostavno šaljite HTTP GET zahteve na bilo koji endpoint naveden ispod.
Metod autentikacije
Nema
Kredencijali nisu potrebni ni za jedan endpoint. Portal je dizajniran kao otvoreni podatkovni resurs za javnu upotrebu.
Konfiguracija servera
KEY_PREFIX & EXPECTED_SCHEMA_VERSION
Ovo su serverske promenljive okruženja koje operator postavlja pri postavljanju. One vezuju portal za imenski prostor podataka jedne organizacije i primenjuju kompatibilnost snimka — nisu API parametri.
Base URL i format odgovora
Osnovna URL adresa zavisi od okruženja. Sve putanje u ovoj dokumentaciji su relativne u odnosu na koren portala. Za lokalnu razvojnu instancu osnovna URL adresa je obično http://localhost:8000.
Format odgovora
JSON (application/json)
Svi endpointi podataka vraćaju Content-Type: application/json. Endpoint za izvoz (/portal/export) vraća binarno preuzimanje datoteke. HTML rute portala vraćaju text/html.
Prozori merenja
1h · 1d · 7d · 14d · 30d
Snimak sadrži unapred agregisane podatke za pet vremenskih prozora. Nisu svi prozori prisutni u svakom snimku — proverite polje supported_windows na GET /meta.
Kodovi grešaka
Sve greške se vraćaju kao JSON sa poljem koje opisuje problem. Health endpointi vraćaju polja umesto toga.
Uspeh
Zahtev je uspešan. Telo odgovora sadrži tražene podatke.
Neispravni parametri
Jedan ili više obaveznih parametara upita nedostaje, prazan je, nije validan ceo broj (za ID-eve), ili ima nepodržanu vrednost (za window ili format).
Resurs nije pronađen
Organizacija, stanica, komponenta ili traženi podaci merenja ne postoje u aktivnom snimku ili nemaju javno dostupnih podataka.
Servis nedostupan
Redis je nedostupan, pokazivač aktivnog snimka nedostaje, ili verzija šeme snimka ne odgovara EXPECTED_SCHEMA_VERSION. Portal nije spreman za posluživanje podataka.
Health
Lagane probe za orkestratore kontejnera i balansere opterećenja. Nijedan endpoint ne zahteva autentikaciju niti pristupa podacima merenja.
Potvrđuje da je proces živ i da HTTP server prihvata veze. Ovaj endpoint ne izvodi nikakav I/O i uvek vraća 200 OK dok god proces radi. Koristite kao probu živosti kontejnera.
Odgovori
| Status | Opis | Primer tela |
|---|---|---|
| 200 | Proces je živ | {"status":"ok","check":"live"} |
Primeri koda
curl -s http://opendata.kosava.cloud/health/live
import requests resp = requests.get("http://opendata.kosava.cloud/health/live") print(resp.json()) # {"status": "ok", "check": "live"}
const resp = await fetch("http://opendata.kosava.cloud/health/live"); const data = await resp.json(); console.log(data); // { status: "ok", check: "live" }
Proverava da li je Redis konekcija ispravna i da li verzija aktivnog snimka odgovara EXPECTED_SCHEMA_VERSION. Vraća 200 sa snapshot_id kada je spreman. Vraća 503 kada Redis nije dostupan, pokazivač snimka nedostaje ili verzija šeme nije kompatibilna. Koristite kao probu spremnosti kontejnera i zdravstvenu kapiju balansera opterećenja.
Odgovori
| Status | Opis | Primer tela |
|---|---|---|
| 200 | Redis dostupan, snimak kompatibilan | {"status":"ok","check":"ready","snapshot_id":"snap_20240101_120000"} |
| 503 | Redis nedostupan ili nekompatibilna šema | {"status":"error","check":"ready","detail":"..."} |
Primeri koda
curl -s http://opendata.kosava.cloud/health/ready
import requests resp = requests.get("http://opendata.kosava.cloud/health/ready") if resp.status_code == 200: print("Ready:", resp.json()["snapshot_id"]) else: print("Not ready:", resp.json()["detail"])
const resp = await fetch("http://opendata.kosava.cloud/health/ready"); const data = await resp.json(); if (resp.ok) console.log("Snapshot:", data.snapshot_id); else console.error("Not ready:", data.detail);
Metapodaci
Endpointi za otkrivanje strukture skupa podataka: organizacije, mreže za praćenje, stanice i komponente merenja. Počnite ovde da saznate koje ID-eve koristiti u upitima merenja. Svi metapodaci dolaze iz aktivnog Redis snimka i samo su za čitanje.
Vraća manifest trenutno aktivnog Redis snimka: vremensku oznaku generisanja, podržane prozore merenja i agregatne brojeve za organizacije, mreže, stanice, komponente i redove merenja. Koristite supported_windows da saznate koje vrednosti prozora su važeće za upite merenja.
Odgovori
| Status | Opis |
|---|---|
| 200 | Objekat manifesta aktivnog snimka |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -s http://opendata.kosava.cloud/meta | python3 -m json.tool
import requests meta = requests.get("http://opendata.kosava.cloud/meta").json() print("Snapshot:", meta["generated_at"]) print("Windows:", meta["supported_windows"]) print("Stations:", meta["counts"]["stations"])
const meta = await fetch("/meta").then(r => r.json()); console.log(meta.supported_windows); // ["1h","1d","7d","14d","30d"] console.log(meta.counts.stations); // 12
Vraća sve organizacije u aktivnom snimku. Pošto je jedna instanca portala vezana za jednu organizaciju putem KEY_PREFIX, ova lista obično sadrži tačno jedan unos. Svaki objekat uključuje organization_id, name i short_name.
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz objekata organizacija |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/organizations
orgs = requests.get("http://opendata.kosava.cloud/organizations").json() org_id = orgs[0]["organization_id"] # typically 1 org
const orgs = await fetch("/organizations").then(r => r.json()); const orgId = orgs[0].organization_id;
Vraća sve mreže za praćenje definisane u aktivnom snimku. Mreže grupišu stanice unutar imenovanog programa merenja ili geografskog područja. Svaki objekat uključuje network_id, network_code, name i short_name.
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz objekata mreža |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/networks
networks = requests.get("http://opendata.kosava.cloud/networks").json() for n in networks: print(n["network_code"], "-", n["name"])
const networks = await fetch("/networks").then(r => r.json()); networks.forEach(n => console.log(n.network_code, n.name));
Vraća sve javne stanice za praćenje u svim organizacijama i mrežama u aktivnom snimku. Svaki objekat uključuje station_id, station_name, station_code, organization_id, network_id, network_code i geografska polja kao što su city i municipality gde su dostupna. Za filtriranje po organizaciji koristite GET /{organization_id}/stations.
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz objekata stanica |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/stations
stations = requests.get("http://opendata.kosava.cloud/stations").json() for s in stations: print(s["station_id"], s["station_name"], s["city"])
const stations = await fetch("/stations").then(r => r.json()); console.log(`${stations.length} stations found`);
Vraća sve komponente merenja (zagađivači i meteorološki parametri) definisane u aktivnom snimku. Svaki objekat uključuje component_id, short_name i unit. Ovde se pojavljuju samo javno vidljive komponente. Meteorološki parametri uključuju brzinu vetra, temperaturu, vlažnost i padavine; parametri zagađenja uključuju čestice (PM10, PM2.5) i gasovite zagađivače.
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz objekata komponenti |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/components
components = requests.get("http://opendata.kosava.cloud/components").json() pm10 = next(c for c in components if c["short_name"] == "PM10") print(pm10["component_id"], pm10["unit"]) # 1001 ug/m3
const components = await fetch("/components").then(r => r.json()); const pm10 = components.find(c => c.short_name === "PM10"); console.log(pm10.component_id, pm10.unit);
Vraća sve javne stanice za praćenje za određenu organizaciju. Oblik odgovora je identičan GET /stations, ali filtriran po datom organization_id. Vraća 404 ako organizacija ne postoji ili nema javnih stanica u aktivnom snimku.
Parametri putanje
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
organization_id |
integer | da | ID organizacije. Dobiti sa GET /organizations. |
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz objekata stanica za organizaciju |
| 404 | Organizacija nije pronađena ili nema javnih stanica |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/1/stations
org_id = 1 stations = requests.get( f"http://opendata.kosava.cloud/{org_id}/stations" ).json() print(f"{len(stations)} stations in org {org_id}")
const orgId = 1; const stations = await fetch(`/${orgId}/stations`).then(r => r.json()); console.log(`${stations.length} stations`);
Vraća detaljne metapodatke za jednu stanicu, uključujući listu javnih komponenti merenja (public_components) dostupnih za tu stanicu. Svaki unos komponente uključuje component_id, short_name i unit. Ovo je polazna tačka za otkrivanje koje komponente mogu biti upitane putem endpointa merenja. Vraća 404 ako organizacija ili stanica ne postoje u aktivnom snimku.
Parametri putanje
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
organization_id |
integer | da | ID organizacije. Dobiti sa GET /organizations. |
station_id |
integer | da | ID stanice. Dobiti sa GET /stations. |
Odgovori
| Status | Opis |
|---|---|
| 200 | Objekat metapodataka stanice sa ugrađenim nizom public_components |
| 404 | Organizacija ili stanica nisu pronađene |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/1/stations/101/meta
meta = requests.get( "http://opendata.kosava.cloud/1/stations/101/meta" ).json() for comp in meta["public_components"]: print(comp["component_id"], comp["short_name"], comp["unit"])
const meta = await fetch("/1/stations/101/meta").then(r => r.json()); meta.public_components.forEach(c => console.log(c.component_id, c.short_name, c.unit) );
Merenja
Endpointi za preuzimanje vremenskih serija podataka o merenjima životne sredine. Sve vrednosti su unapred izračunate u aktivnom Redis snimku — nema agregacije u realnom vremenu. Koristite endpointe metapodataka da biste najpre pronašli važeće ID-eve organizacije, stanice i komponente.
Vraća normalizovane podatke vremenskih serija za jednu komponentu na jednoj stanici tokom traženog vremenskog prozora. Sva četiri parametra upita su obavezna. Odgovor uključuje naziv stanice, detalje komponente, korišćeni prozor i niz points sortiran uzlazno po datumu i vremenu. Svaka tačka ima date (GGGG-MM-DD), time (HH:MM) i numeričku vrednost value. Parametar window mora biti jedan od: 1h, 1d, 7d, 14d, 30d — i mora biti prisutan u supported_windows snimka.
Parametri upita
| Naziv | Tip | Obavezno | Opis | Primer |
|---|---|---|---|---|
organization_id |
integer | da | ID organizacije | 1 |
station_id |
integer | da | ID stanice | 101 |
component_id |
integer | da | ID komponente | 1001 |
window |
string | da | Vremenski prozor. Jedan od: 1h 1d 7d 14d 30d | 1d |
Odgovori
| Status | Opis |
|---|---|
| 200 | Normalizovano telo vremenskih serija sa nizom points |
| 400 | Nedostaje, prazan ili neispravan parametar; nepodržana vrednost prozora |
| 404 | Stanica ili komponenta nije pronađena, ili nema podataka za prozor |
| 503 | Snimak nedostupan |
Primeri koda
curl -s \ "http://opendata.kosava.cloud/measurements?organization_id=1&station_id=101&component_id=1001&window=1d"
import requests resp = requests.get( "http://opendata.kosava.cloud/measurements", params={ "organization_id": 1, "station_id": 101, "component_id": 1001, "window": "1d", }, ) resp.raise_for_status() data = resp.json() print(f"{data['station_name']} — {data['component_short_name']} ({data['unit']})") for pt in data["points"]: print(pt["date"], pt["time"], pt["value"])
const params = new URLSearchParams({ organization_id: "1", station_id: "101", component_id: "1001", window: "1d", }); const resp = await fetch(`/measurements?${params}`); if (!resp.ok) throw new Error(await resp.text()); const data = await resp.json(); console.log(`${data.station_name} — ${data.component_short_name} (${data.unit})`); data.points.forEach(pt => console.log(pt.date, pt.time, pt.value));
Vraća sva merenja komponenti zabeležena u poslednjem satu za određenu stanicu. Telo odgovora sadrži niz hours gde svaki unos ima date (ISO-8601 string datuma), time (HH:MM) i listu components. Svaki unos komponente uključuje component_id i numeričku vrednost value. Vraća 404 ako stanica ne postoji ili nema podataka za poslednji sat.
Parametri putanje
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
organization_id |
integer | da | ID organizacije |
station_id |
integer | da | ID stanice |
Odgovori
| Status | Opis |
|---|---|
| 200 | Telo za poslednji sat sa nizom hours, svaki sadrži listu components |
| 404 | Stanica nije pronađena ili nema podataka za poslednji sat |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/1/stations/101/measurements/last_hour
data = requests.get( "http://opendata.kosava.cloud/1/stations/101/measurements/last_hour" ).json() for hour in data["hours"]: print(hour["date"], hour["time"]) for comp in hour["components"]: print(" component", comp["component_id"], "=", comp["value"])
const data = await fetch("/1/stations/101/measurements/last_hour") .then(r => r.json()); data.hours.forEach(hour => { console.log(hour.date, hour.time); hour.components.forEach(c => console.log(" component", c.component_id, "=", c.value)); });
Vraća sva merenja komponenti zabeležena tokom poslednjih 24 sata za određenu stanicu. Struktura tela identična je last_hour: niz hours gde svaki unos ima date, time i components. Sve javno izložene komponente stanice su uključene u svaki satni unos gde postoje podaci. Vraća 404 ako stanica ne postoji ili nema podataka za poslednjih 24 sata.
Parametri putanje
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
organization_id |
integer | da | ID organizacije |
station_id |
integer | da | ID stanice |
Odgovori
| Status | Opis |
|---|---|
| 200 | Telo za poslednjih 24 sata sa nizom hours do 24 satna unosa |
| 404 | Stanica nije pronađena ili nema podataka za poslednjih 24 sata |
| 503 | Snimak nedostupan |
Primeri koda
curl -s http://opendata.kosava.cloud/1/stations/101/measurements/last_24h
data = requests.get( "http://opendata.kosava.cloud/1/stations/101/measurements/last_24h" ).json() print(f"{len(data['hours'])} hours of data")
const data = await fetch("/1/stations/101/measurements/last_24h") .then(r => r.json()); console.log(`${data.hours.length} hours of data`);
Izvoz
Preuzmite vremenske serije merenja kao strukturisanu datoteku. Podržani formati su CSV (UTF-8), XLSX (Excel) i ODS (LibreOffice Calc). Izvezena datoteka sadrži sve kontekstualne kolone — organizacija, mreža, stanica, komponenta, datum, vreme, jedinica i numerička vrednost.
Gradi i strujno prenosi datoteku tabele za preuzimanje koja sadrži podatke vremenskih serija merenja za jednu komponentu na jednoj stanici. Svih pet parametara upita je obavezno. Prozor 1h nije podržan za izvoz. Izvezena datoteka sadrži jedan red po tački merenja sa kolonama: organization_id, organization_name, station_id, station_name, station_code, network_id, network_code, date, time, component_id, component_short_name, unit, value. Numeričke vrednosti su formatirane na dve decimale.
Parametri upita
| Naziv | Tip | Obavezno | Opis | Primer |
|---|---|---|---|---|
organization_id |
integer | da | ID organizacije | 1 |
station_id |
integer | da | ID stanice | 101 |
component_id |
integer | da | ID komponente | 1001 |
window |
string | da | Vremenski prozor. Jedan od: 1d 7d 14d 30d (1h nije podržan) | 7d |
format |
string | da | Format datoteke. Jedan od: csv xlsx ods | csv |
Odgovori
| Status | Content-Type | Opis |
|---|---|---|
| 200 | text/csv / application/vnd.openxmlformats-officedocument.spreadsheetml.sheet / application/vnd.oasis.opendocument.spreadsheet |
Preuzimanje datoteke sa Content-Disposition: attachment |
| 400 | application/json | Nedostaje/neispravan parametar ili nepodržan prozor/format |
| 404 | application/json | Stanica ili komponenta nije pronađena, ili nema podataka za prozor |
| 503 | application/json | Snimak nedostupan |
Primeri koda
# Download as CSV curl -OJ \ "http://opendata.kosava.cloud/portal/export?organization_id=1&station_id=101&component_id=1001&window=7d&format=csv" # Download as XLSX curl -OJ \ "http://opendata.kosava.cloud/portal/export?organization_id=1&station_id=101&component_id=1001&window=7d&format=xlsx"
import requests, re resp = requests.get( "http://opendata.kosava.cloud/portal/export", params={ "organization_id": 1, "station_id": 101, "component_id": 1001, "window": "7d", "format": "csv", }, ) resp.raise_for_status() # Extract filename from Content-Disposition header cd = resp.headers.get("Content-Disposition", "") m = re.search(r'filename="(.+?)"', cd) filename = m.group(1) if m else "export.csv" with open(filename, "wb") as f: f.write(resp.content) print(f"Saved: {filename}")
const params = new URLSearchParams({ organization_id: "1", station_id: "101", component_id: "1001", window: "7d", format: "csv", }); const resp = await fetch(`/portal/export?${params}`); if (!resp.ok) throw new Error(await resp.text()); const blob = await resp.blob(); const cd = resp.headers.get("content-disposition") ?? ""; const filename = (cd.match(/filename="(.+?)"/) ?? [])[1] ?? "export.csv"; // Trigger browser download const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = filename; a.click();
HVD API (/api/v1)
Javni HVD-compliant API namespace u skladu sa Sprovodbenom uredbom Komisije (EU) 2023/138 i SEPA HVD profilom. Sve rute vraćaju mašinski čitljiv JSON sa standardizovanim poljima: data_status=preliminary, aggregation_type=hourly_mean, time_start_utc/time_end_utc u ISO 8601 UTC formatu. Postojeći /meta, /stations i /measurements ugovor ostaje netaknut radi kompatibilnosti.
Vraća kompletan HVD descriptor: schema_version, dataset_version, snapshot_id, retention_days, deklarisani data_status (preliminary), aggregation_type (hourly_mean), supported_windows, applicable_legislation (ELI link na 2023/138), licencu, i linkove na pravne stranice (license, terms, qos, contact, dataset) i dokumentaciju (docs, redoc, openapi). Pogodno za harvester-e i klijentske integracione provere.
Odgovori
| Status | Opis |
|---|---|
| 200 | Pun HVD descriptor sa licencom, retention politikom i linkovima. |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -s http://opendata.kosava.cloud/api/v1/metadata | python3 -m json.tool
import requests m = requests.get("http://opendata.kosava.cloud/api/v1/metadata").json() print(m["data_status"], m["retention_days"]) print(m["applicable_legislation"])
const meta = await fetch("/api/v1/metadata").then(r => r.json()); console.log(meta.license, meta.retention_days);
Vraća sve monitoring stanice u HVD obliku (Komponenta A standarda). Svaka stanica nosi station_id (string), station_name, latitude/longitude, municipality, station_type (traffic/urban/background/industrial/rural/other), operator, active, last_updated_utc i opciona polja (elevation_m, address, start_date, end_date, notes). Podržani filteri: active, municipality (case-insensitive), station_type, bbox (min_lon,min_lat,max_lon,max_lat).
Parametri upita
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
active | boolean | ne | Filter na aktivne stanice. true vraća samo aktivne, false samo neaktivne. |
municipality | string | ne | Filter po imenu opštine, case-insensitive exact match. |
station_type | string | ne | Filter po HVD enum tipu stanice (traffic, urban, background, industrial, rural, other). |
bbox | string | ne | Bounding box "min_lon,min_lat,max_lon,max_lat" u WGS84. Vraća stanice unutar boxa. |
Primeri koda
curl -s "http://opendata.kosava.cloud/api/v1/stations?municipality=Kikinda"
stations = requests.get( "http://opendata.kosava.cloud/api/v1/stations", params={"bbox": "19,44,21,46"}, ).json() for s in stations: print(s["station_id"], s["station_name"], s["municipality"])
const stations = await fetch("/api/v1/stations?active=true").then(r => r.json()); stations.forEach(s => console.log(s.station_id, s.municipality));
Vraća kontrolisani rečnik mernih parametara (Komponenta B standarda). Svaki zapis ima parameter_code (npr. PM10, PM2.5, NO2, O3, SO2), parameter_name, unit i fiksni averaging_period=1h. Opciono: cas_number, description.
Odgovori
| Status | Opis |
|---|---|
| 200 | Niz HVD parameter zapisa. |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -s http://opendata.kosava.cloud/api/v1/parameters
params = requests.get("http://opendata.kosava.cloud/api/v1/parameters").json() codes = [p["parameter_code"] for p in params] # ['SO2', 'PM10', 'O3', 'NO2', 'PM2.5', ...]
const params = await fetch("/api/v1/parameters").then(r => r.json());
Vraća satno upročešena merenja u HVD obliku (Komponenta C). Svaki record ima station_id, parameter_code, time_start_utc, time_end_utc, value, unit, data_status=preliminary, aggregation_type=hourly_mean, published_at_utc, updated_at_utc, coverage. Prozor se automatski seče na rolling 30 dana; meta blok odgovora navodi requested_window i actual_window plus out_of_retention_window flag. Bez filtera vraća sve stanice × svi parametri (može biti veliki payload).
Parametri upita
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
from | datetime | ne | Početak prozora, ISO 8601 datetime (npr. 2026-04-01T00:00:00Z). Bez TZ tretira se kao UTC. Default: generated_at - retention_days. |
to | datetime | ne | Kraj prozora, ISO 8601 datetime. Bez TZ tretira se kao UTC. Default: generated_at. |
station_id | string | ne | Filter na jednu stanicu. HVD station_id je string verzija internog ID-a. |
parameter_code | string | ne | Filter na jedan parametar (npr. PM10, PM2.5, NO2). |
Primeri koda
curl -s "http://opendata.kosava.cloud/api/v1/observations?station_id=1¶meter_code=PM10"
obs = requests.get( "http://opendata.kosava.cloud/api/v1/observations", params={ "from": "2026-04-01T00:00:00Z", "to": "2026-04-08T00:00:00Z", "parameter_code": "PM2.5", }, ).json() print(obs["meta"]["actual_window"]) print(len(obs["data"]), "records")
const q = new URLSearchParams({station_id: "1", parameter_code: "PM10"}); const resp = await fetch(`/api/v1/observations?${q}`).then(r => r.json()); console.log(resp.meta.out_of_retention_window);
Vraća listu bulk resursa za aktivni snapshot. Svaki zapis ima name, format, content_type, size_bytes, sha256, download_url. Bundle uključuje stations.csv/geojson, parameters.csv/json, observations CSV i Parquet (kraći ~13× od CSV-a), README.md sa data dictionary-jem i CHECKSUMS.sha256. Lazy on-demand build sa snapshot-id keyed cache-om.
Odgovori
| Status | Opis |
|---|---|
| 200 | Index bulk paketa sa SHA256 sumama. |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -s http://opendata.kosava.cloud/api/v1/bulk | python3 -m json.tool
index = requests.get("http://opendata.kosava.cloud/api/v1/bulk").json() for r in index["resources"]: print(r["name"], r["size_bytes"], r["sha256"])
const idx = await fetch("/api/v1/bulk").then(r => r.json()); console.log(idx.snapshot_id, idx.resources.length);
Servira jedan bulk fajl kao attachment. Response zaglavlja uključuju Content-Disposition (attachment; filename="..."), Content-Length, Content-Type i X-Content-SHA256 (mora se podudarati sa sha256 u indeksu).
Parametri putanje
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
filename | string | da | Ime bulk resursa iz indeksa (npr. observations_hourly_preliminary_last30days.parquet). |
Odgovori
| Status | Opis |
|---|---|
| 200 | Bulk fajl kao attachment sa Content-Disposition i X-Content-SHA256 zaglavljima. |
| 404 | Traženi fajl ne postoji u trenutnom bulk paketu. |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -O http://opendata.kosava.cloud/api/v1/bulk/observations_hourly_preliminary_last30days.parquet
import requests, pyarrow.parquet as pq from io import BytesIO data = requests.get("http://opendata.kosava.cloud/api/v1/bulk/observations_hourly_preliminary_last30days.parquet").content table = pq.read_table(BytesIO(data)) print(table.num_rows, table.column_names)
const blob = await fetch("/api/v1/bulk/stations.geojson").then(r => r.blob()); // feed blob to Leaflet, OpenLayers, etc.
Vraća DCAT-AP HVD katalog kao application/ld+json sa @context i @graph od 16 nodova: jedan dcat:Catalog, foaf:Organization (publisher) i vcard:Organization (kontakt), tri dcat:Dataset (stations, parameters, observations), devet dcat:Distribution (API + CSV/GeoJSON/JSON/Parquet po datasetu), jedan dcat:DataService. Svaki Dataset/Distribution nosi dcatap:applicableLegislation (ELI 2023/138) i dcatap:hvdCategory (Earth observation and environment). Pogodno za harvest na EU/nacionalnim portalima.
Odgovori
| Status | Opis |
|---|---|
| 200 | DCAT-AP HVD katalog kao application/ld+json sa 16-node @graph. |
| 503 | Snimak nedostupan ili nekompatibilan |
Primeri koda
curl -s -H "Accept: application/ld+json" http://opendata.kosava.cloud/api/v1/dcat
cat = requests.get("http://opendata.kosava.cloud/api/v1/dcat").json() datasets = [n for n in cat["@graph"] if n.get("@type") == "dcat:Dataset"] print(len(datasets), "datasets")
const cat = await fetch("/api/v1/dcat").then(r => r.json()); // JSON-LD compatible with rdflib, jsonld.js, Apache Jena
Rečnik polja (HVD Sekcija 11)
Strukturni rečnik svakog polja iz tri komponente skupa podataka. Definicije su dostupne mašinski čitljivo na endpoint-u /api/v1/data-dictionary i ovde u tri jezika. Konstantne vrednosti i reference između komponenti su naznačene u tabelama.
Vraća JSON sa definicijama svih polja u tri komponente (stations, parameters, observations) plus listu zabranjenih polja. Pogodan za klijentske validacije i automatsku generaciju formi/dokumentacije.
Parametri upita
| Naziv | Tip | Obavezno | Opis |
|---|---|---|---|
language |
string | ne | Jezik definicija. Jedan od: sr-Latn, sr-Cyrl, en. Default: sr-Latn. |
Zabranjena polja (HVD Sekcija 5.3.2): validated, qa_flag, compliance, exceedance
Identifikacija i geolokacija mernih mesta. Endpoint /api/v1/stations vraća listu sa svim poljima ispod; bulk distribucije su stations.csv i stations.geojson.
| Naziv | Tip | Obavezno | Konstanta | Referenca | Opis |
|---|---|---|---|---|---|
station_id |
string | da | Jedinstveni identifikator merne stanice. Stabilan kroz vreme i kroz snapshot generacije; služi kao primarni ključ za stanicu u svim distribucijama i kao referenca u observations.station_id. | ||
station_name |
string | da | Čovekoljudsko ime stanice (npr. „Kikinda Centar"). Može sadržavati lokalnu transliteraciju. | ||
station_code |
string | ne | Operatorski kod stanice (npr. „RS1002A") koji se često koristi u izveštajnim sistemima. Dodatno stabilan identifier; nije deo HVD obaveznog skupa ali se emituje radi interoperabilnosti. | ||
latitude |
decimal | da | Geografska širina stanice u WGS84 koordinatnom sistemu, decimalni stepen. | ||
longitude |
decimal | da | Geografska dužina stanice u WGS84 koordinatnom sistemu, decimalni stepen. | ||
municipality |
string | da | Naziv opštine u kojoj se stanica nalazi. Može biti null kada izvor podataka ne raspolaže ovom informacijom (polje obavezno postoji u shemi). | ||
station_type |
enum | da | Tip lokacije stanice po HVD klasifikaciji. Dozvoljene vrednosti: traffic, urban, background, industrial, rural, other. Može biti null ako tip nije poznat. | ||
operator |
string | da | Naziv organizacije koja operiše stanicom. Trenutno se izvodi iz organization.name na nivou portal instance. | ||
active |
boolean | da | Da li stanica trenutno aktivno emituje merenja. true ako je stanica prisutna u aktivnom snapshotu i operativna; false ako je zaustavljena ili van mreže. | ||
last_updated_utc |
datetime | da | Trenutak poslednjeg ažuriranja metapodataka stanice u ISO 8601 UTC formatu. Trenutno se izvodi iz manifest.generated_at (snapshot-level timestamp). | ||
elevation_m |
decimal | ne | Nadmorska visina stanice u metrima. Opciono polje, null ako nije dostupno. | ||
address |
string | ne | Postanska ili ulična adresa stanice. Opciono polje, null ako nije dostupno. | ||
start_date |
date | ne | Datum početka rada stanice u ISO 8601 formatu (YYYY-MM-DD). Opciono polje. | ||
end_date |
date | ne | Datum prestanka rada stanice u ISO 8601 formatu. null ako stanica još radi. | ||
notes |
string | ne | Slobodan tekst sa dodatnim napomenama o stanici. Opciono polje. | ||
network_id |
integer | ne | Identifikator merne mreže kojoj stanica pripada. Nije deo HVD obaveznog skupa ali se emituje radi navigacije po mrežama. | ||
network_code |
string | ne | Operatorski kod merne mreže. Nije deo HVD obaveznog skupa. |
Kontrolisani rečnik mernih veličina. Endpoint /api/v1/parameters vraća niz; bulk distribucije su parameters.csv i parameters.json.
| Naziv | Tip | Obavezno | Konstanta | Referenca | Opis |
|---|---|---|---|---|---|
parameter_code |
string | da | Sifra parametra (npr. PM10, PM2.5, NO2, O3, SO2). Stabilan ključ koji se referencira iz observations.parameter_code. | ||
parameter_name |
string | da | Puno čovekoljudsko ime parametra (npr. „Particulate matter <= 2.5 um"). Trenutno fallback-uje na parameter_code dok snapshot ne počne da emituje component.name (v1.3.0). | ||
unit |
string | da | Jedinica mere u UCUM ili sličnoj notaciji (npr. „ug.m-3" za mikrograme po kubnom metru). Konzistentna između parameters i observations distribucija. | ||
averaging_period |
string | da | 1h |
Period upročešavanja vrednosti. Konstantno „1h" u v1.0 — sve vrednosti su satni proseci. | |
cas_number |
string | ne | CAS broj zagadjivaca (npr. „10102-44-0" za NO2). Opciono, null ako nije dostupno. | ||
description |
string | ne | Slobodan tekst sa dodatnim opisom parametra. Opciono polje. |
Satno upročešena merenja sa svim stanicama i parametrima u rolling 30-day prozoru. Endpoint /api/v1/observations vraća JSON sa data + meta blokom; bulk distribucije su observations_hourly_preliminary_last30days.csv i .parquet.
| Naziv | Tip | Obavezno | Konstanta | Referenca | Opis |
|---|---|---|---|---|---|
station_id |
string | da | stations.station_id |
Identifikator merne stanice. Referenca na stations.station_id; mora postojati u istom snapshotu. | |
parameter_code |
string | da | parameters.parameter_code |
Šifra parametra. Referenca na parameters.parameter_code; mora postojati u istom snapshotu. | |
time_start_utc |
datetime | da | Početak satnog intervala (uključivo) u ISO 8601 UTC formatu sa Z sufiksom. Vremenski opseg zapisa je [time_start_utc, time_end_utc). | ||
time_end_utc |
datetime | da | Kraj satnog intervala (isključivo) u ISO 8601 UTC formatu. Uvek time_start_utc + 1h. | ||
value |
decimal | da | Sat na koncentracija parametra na stanici, u jedinici naznačenoj poljem unit. null ako merenje nije dostupno za dati interval. | ||
unit |
string | da | parameters.unit |
Jedinica mere za polje value. Konzistentno sa parameters.unit za isti parameter_code. | |
data_status |
string | da | preliminary |
Status validacije podatka. Konstantno „preliminary" — podaci nisu prošli formalnu QA/QC validaciju i nisu namenjeni regulatornoj proceni. | |
aggregation_type |
string | da | hourly_mean |
Tip agregacije vrednosti. Konstantno „hourly_mean" — vrednost predstavlja prosek u 60-minutnom intervalu [time_start_utc, time_end_utc). | |
published_at_utc |
datetime | da | Trenutak prvog objavljivanja vrednosti u ISO 8601 UTC. U v1.0 izvodi se iz manifest.generated_at (snapshot-level); per-record verzija dolazi sa snapshot v1.3.0. | ||
updated_at_utc |
datetime | da | Trenutak poslednje izmene vrednosti u ISO 8601 UTC. Ako vrednost nikad nije menjana, jednako published_at_utc. Trenutno snapshot-level; per-record verzija dolazi sa snapshot v1.3.0. | ||
coverage |
decimal | ne | Relativna pokrivenost satnog intervala u opsegu [0, 1]. Vrednost 1.0 znači punu pokrivenost (60/60 minuta), 0.5 znači pola interval. null ako sistem ne raspolaže ovom informacijom (polje obavezno postoji u shemi). |
Pravne i operativne stranice
Pravni okviri i operativna obeleženja koja portal javno objavljuje radi HVD compliance-a. Svaka stranica je dostupna na sva tri jezika i u obe teme.
Opis skupa podataka
HVD-style opis skupa po Sekciji 9.2 standarda: naslov, sažetak, distribucije (API + bulk + DCAT), pravni osnov.
Licenca
Licenca otvorenih podataka po Zakonu o e-upravi (član 26), funkcionalno ekvivalentna CC BY: slobodno korišćenje uz navođenje izvora.
Uslovi korišćenja
Uslovi koriscenja API-ja: licenca, preliminary disclaimer, 30-day retention, odricanje od regulatorne odgovornosti, kontakt.
QoS kriterijumi
Ciljna mesečna dostupnost 99%, bez rate limit-a u v1.0, najava održavanja 24h unapred, snapshot se osvežava jednom dnevno.
Kontakt
Kontakt informacije za pitanja o podacima, tehničkoj podršci i pravnim aspektima.