Sari la conținut

API v1 · OpenAPI 3.1

API și date deschise pentru cotele Dunării

API JSON gratuit pentru cotele Dunării: stații cu pragurile LDC/HDC, serii zilnice, GeoJSON și contract OpenAPI 3.1, cu limite de cereri și exemple de cod.

Adresa de bază
https://danubealert.arcm.ro/api/v1
Autentificare
Authorization: Bearer <key>

Ia o cheie API gratuită →Contractul OpenAPI 3.1

Prezentare

API-ul public v1 oferă datele hidrologice din bazinul Dunării în format JSON: stațiile cu pragurile LDC/HDC, citirile și prognozele, pragurile oficiale, punctele critice de navigație, buletinele hidrologice, exportul GeoJSON și starea surselor. Contractul complet e la /api/v1/openapi.json (OpenAPI 3.1).

Planuri și limite

Anonim (fără antet): 60 cereri pe minut, CORS * pe GET. Cu cheie de integrator (Authorization: Bearer <cheie>): 600 cereri pe minut. Cheile se creează gratuit din contul tău. O cheie malformată, necunoscută sau revocată primește 401 (WWW-Authenticate: Bearer error="invalid_token"), nu acces anonim; o cheie revocată nu mai merge imediat.

  • Anonim

    60cereri / minut

    Fără antet, CORS * pe GET — destul ca să încerci fiecare rută.

  • Cheie API gratuită

    600cereri / minut

    Authorization: Bearer <cheie>, creată din contul tău, afișată o singură dată.

  • Rute grele

    10cereri / minut

    Seriile și exporturile ( observations, export ), pe cheie sau IP.

Exemplu

Ultimul nivel zilnic al unei stații, cu curl și cu TypeScript.

curl
curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/observations"
TypeScript
// Nivelul de azi la Budapesta
const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/observations?interval=daily&from=2026-10-01', {
  headers: { Authorization: `Bearer ${process.env.DANUBEALERT_KEY}` },
})
const { data } = await r.json()
console.log(data.at(-1)) // { observed_at: "2026-10-21T00:00:00Z", level_cm: 468 }

Resurse

Toate rutele API-ului public v1, doar citire ( GET ), cu parametrii lor și o cerere gata de rulat.

Exemple pe rută

Fiecare rută are mai jos cererea curl, JavaScript și Python, limita ei de rată și blocul `_attribution` pe care trebuie să-l afișezi lîngă date.

Blocul `_attribution`
{
  "source": "National hydrological services of the Danube basin (see /v1/meta/sources)",
  "url": "https://danubealert.arcm.ro/en/about",
  "data_updated_at": "2026-10-21T00:00:00Z"
}
_attribution · /export/daily
{
  "source": "National hydrological services of the Danube basin (see /v1/meta/sources)",
  "url": "https://danubealert.arcm.ro/en/about",
  "license": {
    "id": "CC-BY-4.0",
    "name": "Creative Commons Attribution 4.0 International",
    "url": "https://creativecommons.org/licenses/by/4.0/"
  },
  "data_updated_at": "2026-10-21T00:00:00Z"
}

Stații

  • GET/api/v1/alerts/confirmLinkul de confirmare din email ( nu pornește nimic )

    Linkul din emailul de confirmare al unei alerte sau al unui raport zilnic, trimis când contul nu și-a dovedit încă adresa. **Nu pornește nimic** ( scannerele de linkuri ale firmelor deschid singure emailurile ): browserul e dus la pagina publică `/{lang}/alerts/confirm`, cu un singur buton care face `POST /alerts/confirm`. Cu `format=json` ( sau `Accept: application/json` ) răspunde doar starea: 200 cu `status` `pending` / `active`, 404 pentru un jeton invalid.

    Parametri

    • t*query
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/alerts/confirm?t=t"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/alerts/confirm?t=t')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/alerts/confirm?t=t", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • POST/api/v1/alerts/confirmPornește alerta sau raportul confirmat

    Singurul pas care pornește abonamentul ( `activ = true` ): butonul paginii de confirmare sau un client, cu jetonul în query ( `t` ) sau în corp ( `{ "t": "…" }` ). Doar un abonament încă în așteptare pornește; unul oprit între timp din cont rămâne oprit. Tot aici se dovedește și adresa contului. Browserul e dus pe pagina publică a abonamentului ( „pornită” ), un client primește JSON ( `kind`: `alert` / `report` ).

    Parametri

    • tquery
  • GET/api/v1/basin-precipitationPrecipitațiile cumulate pe 24 / 72 h pe sub-bazine, cu stația din aval

    Ploaia cumulată pe ultimele 24 h și 72 h încheiate, pe sub-bazine: punctul de calcul e o stație de pe cursul superior, iar rândul se leagă de stația din aval — semnalul precursor al creșterii nivelului acolo. Seria orară vine dintr-o sursă meteo deschisă ( CC BY 4.0, vezi `_attribution` ); `window_end` e momentul până la care sunt cumulate orele ( exclusiv ), iar `hours_24h` / `hours_72h` spun câte ore cu valoare au intrat în fiecare fereastră. Un sub-bazin a cărui rulare a picat păstrează ultimul `window_end`.

    Parametri

    • stationquery
    • riverquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/basin-precipitation"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/basin-precipitation')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/basin-precipitation", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/countries/{code}/stationsStațiile unei țări

    Aceleași rânduri ca `/stations`, filtrate pe țară; fiecare are blocul `quality` ( sursa de referință, ultima citire, starea G3 și reperul cotei zero a stației ).

    Parametri

    • code*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/countries/HU/stations"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/countries/HU/stations')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/countries/HU/stations", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/report/todayRaportul zilei: starea pe bazin, ce se schimbă azi, stațiile sub/peste praguri, prognoza 24–72 h

    Raportul zilei ca un singur obiect, pentru pagina `/{lang}/today` ( UX-9 ). `basin` este exact agregatul „Situația azi” ( totalul și rândurile pe țară ), `changes` este blocul F4 ( variația pe 24 h, unda Q74, abaterea D2 ), `thresholds` listează stațiile cu citire proaspătă sub LDC / peste HDC ( cu pragul, nivelul și diferența ), iar `forecast` dă prognoza **24–72 h** din G2 ( sursa, emiterea, orizontul sursei, banda min–max pe orizont și `orientativ` ), doar pentru stațiile cu o prognoză semnificativă: atinge un prag ori mișcă cel puțin 25 cm față de nivelul de acum. Lista e plafonată ( 12 pe bazin, 3 pe țară ), cu totalul dinainte de plafon; zilele 4–5 (+96 / +120 h) nu intră în raport.

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/report/today"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/report/today')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/report/today", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stationsLista stațiilor

    Lista paginată a stațiilor, cu nivelul, prognoza și blocul `quality` pe fiecare rând: sursa de referință, ora ultimei citiri, starea G3 ( proaspătă / „citire veche” / fără date ) și reperul cotei zero a stației ( național / altul / absolut / necunoscut ).

    Parametri

    • countryquery
    • riverquery
    • qquery
    • limitquery
    • next_cursorquery
    • sortquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}Stația și pragurile LDC/HDC

    Fișa stației: pragurile LDC/HDC, coordonatele, prospețimea sursei de referință ( Q88 ), acoperirea seriei pe 365 de zile ( Q94 ), blocul `quality` — sursa de referință, ultima citire, starea G3 și reperul cotei zero a stației ( H4 ) —, blocul `anomaly` — abaterea nivelului de azi față de climatologia zilei ( D1 ), absent sub 10 ani de referință — și, când stația are prognoză, blocul `forecast` cu sursa, `horizon_hours` ( cât de departe merge prognoza ) și orizonturile cu banda min–max ( G2, UX-11 §8.1 p. 6 ).

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/eventsEvenimentele istorice ale stației: viituri și secete majore

    Viiturile și secetele majore documentate pentru stație, cele mai noi primele ( anul, apoi ziua vârfului ). Fiecare rând are tipul, anul, ziua vârfului când sursa o publică, valoarea măsurată la stație, cu unitatea ei, codul sursei, instituția și URL-ul public. `?tip=viitura|seceta` filtrează tipul. Rândurile vin din colecția editorială `evenimente-istorice`, unde sursa și dovada fiecărui rând sunt obligatorii. `_attribution.data_updated_at` e cea mai nouă dată de verificare a rândurilor întoarse.

    Parametri

    • slug*path
    • tipquery
    • limitquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/events"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/events')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/events", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/neighborsVecinii amonte/aval și confluențele

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/neighbors"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/neighbors')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/neighbors", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/stationsLista stațiilor ( v2, cursor + fields + format )

    Aceleași date ca `/v1/stations`, cu contractul de listă v2: paginare cursor keyset, `fields=` și `format=json|csv|geojson`. Răspunsul e cacheabil (`ETag`, `Last-Modified`, `Cache-Control`), iar `If-None-Match` întoarce `304`.

    Parametri

    • countryquery
    • riverquery
    • qquery
    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/stations"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/stations')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/stations", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/wizardDatele asistentului de alerte: sectoare, țări, râuri și căutare

    Sectoarele Dunării în ordinea izvor → vărsare ( pe țări, cu intervalul de kilometraj și stațiile sectorului ), plus râurile fiecărei țări, ordonate după numărul de stații. Cu `q`, caută stații și râuri după nume, tolerant la diacritice și la alfabetul chirilic; `limit` ( 1…50 ) taie fiecare listă. Răspuns cache-uit ca restul catalogului.

    Parametri

    • qquery
    • limitquery
    • partequery
    • taraquery
    • langquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/wizard"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/wizard')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/wizard", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Măsurători și prognoze

  • GET/api/v1/forecast/accuracyAcuratețea prognozelor oficiale față de citirile reale, pe sursă și orizont10/min

    Backtest al rândurilor din `forecasts` față de citirile reale din `readings`, pe sursă × orizont ( +24 / +48 / +72 h ): eroarea medie absolută ( `mae_cm` ), bias-ul cu semn ( `bias_cm`, pozitiv = prognoza a fost prea sus ) și procentul citirilor în banda min–max publicată ( `within_band_pct`, doar pe eșantioanele cu bandă ). Lista are toate sursele cu prognoză în fereastră, inclusiv cele fără perechi încă ( `samples: 0`, medii `null` ). Fereastra implicită: 90 de zile după momentul țintă; fiecare prognoză se compară cu cea mai apropiată citire din ±6 h, preferând seria emitentului, altfel sursa de referință a stației. Fără citire în fereastră, prognoza nu intră în eșantion. Fără `station`, agregatul e pe tot bazinul; cu `station`, doar stația cerută — aceleași cifre ca `/stations/{slug}/forecast-accuracy`. Endpoint greu: 10 cereri/min.

    Parametri

    • stationquery
    • daysquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/forecast/accuracy"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/forecast/accuracy')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/forecast/accuracy", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/measurementsTemperatura apei, debit, temperatura aerului

    Parametri

    • station*query
    • measurequery
    • fromquery
    • toquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/measurements?station=budapest"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/measurements?station=budapest')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/measurements?station=budapest", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/observationsCompară până la 6 stații într-un răspuns10/min

    Aceleași reguli ca observațiile unei stații; `interval` implicit `daily` și rate limit „greu” (10/min).

    Parametri

    • stations*query
    • fromquery
    • toquery
    • intervalquery
    • riverquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/observations?stations=budapest%2Cmohacs"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/observations?stations=budapest%2Cmohacs')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/observations?stations=budapest%2Cmohacs", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/climatologyClimatologia zilei: media și percentilele din tot istoricul10/min

    Seria de referință a stației, pe fiecare zi calendaristică ( `MM-DD` ): din tot istoricul rollup-ului zilnic, câți ani au contribuit, media, mediana, percentilele 10 / 25 / 75 / 90, minimul, maximul și abaterea standard. Valoarea unei zile e prima citire a zilei locale, din sursa de referință efectivă a stației. Baza pentru „azi e cu X cm sub normalul zilei”; abaterea propriu-zisă e în blocul `anomaly` al fișei stației și în `GET /summary/today`.

    Parametri

    • slug*path
    • dayquery
    • limitquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/climatology"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/climatology')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/climatology", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/dischargeSeria de debit ( Q, m³/s ) a stației

    Seria de debit din tabela `masuratori` ( mărimea `debit` ), scrisă de serviciile hidrologice naționale. Un răspuns conține o singură sursă ( `source` ): fără `source=` se ia sursa celei mai noi măsurători de debit, ca seriile unor surse diferite să nu se amestece. `interval=hourly|daily` agregă prin medie. Endpoint greu: 10 cereri/minut anonim.

    Parametri

    • slug*path
    • sourcequery
    • fromquery
    • toquery
    • intervalquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/discharge"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/discharge')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/discharge", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/forecastPrognoza stației ( unde există )

    Ultima emisiune dintr-o singură sursă ( `source` ); seriile unor surse diferite nu se amestecă. `horizon_hours` spune cât de departe merge prognoza emisiunii ( de la +48 h la +120 h, după sursă ), iar fiecare orizont are banda min–max publicată de sursă ( `level_min_cm` / `level_max_cm`, `null` unde nu o dă ). Zilele 4–5 ( +96 / +120 h ) au `orientativ: true`: apar în date, dar nu declanșează alerte — motorul folosește doar 24–72 h.

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/forecast"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/forecast')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/forecast", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/forecast-accuracyAcuratețea prognozelor stației, pe sursă și orizont10/min

    Backtest-ul prognozelor emise pentru stația din cale, față de citirile ei reale, pe sursă × orizont ( +24 / +48 / +72 h ): eroarea medie absolută ( `mae_cm` ), bias-ul cu semn ( `bias_cm`, pozitiv = prognoza a fost prea sus ) și procentul citirilor în banda min–max publicată ( `within_band_pct` ). Lista are **toate sursele cu prognoză** pe stație în fereastră; o sursă fără nicio pereche prognoză–citire încă apare, cu `samples: 0` și mediile `null`. Fereastra implicită: 90 de zile după momentul țintă; citirea se ia la ±6 h, preferând seria emitentului, altfel sursa de referință a stației. Aceleași cifre ca `/forecast/accuracy?station=<slug>`. Endpoint greu: 10 cereri/min.

    Parametri

    • slug*path
    • daysquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/forecast-accuracy"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/forecast-accuracy')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/forecast-accuracy", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/iceGhețurile din buletinele naționale, pe stație și zi

    Fenomenele de iarnă publicate în buletinele naționale, normalizate pe stație și zi. Sursa de azi e un buletin național zilnic: coloana `L` ( indice 0–8 ) devine `code`, iar `phenomena` conține codurile canonice în engleză ( `ice_floe`, `ice_bridge`, `shore_ice`… ). O zi cu indicele 0 e o observație reală ( `ice: false`, `code: 0`, `phenomena: []` ), nu lipsă de date. RO / BG / RS / HU nu publică fenomenul pe stație în buletinul zilnic ( vezi descrierea surselor ), deci nu apar aici.

    Parametri

    • slug*path
    • limitquery
    • fromquery
    • toquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/ice"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/ice')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/ice", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/observationsSerie de măsurători ( nivel în cm )10/min

    Endpoint greu pentru istoric lung anonim: 10 cereri/minut ( §3 ). Implicit seria e a **sursei de referință** a stației ( sursa națională; `source` în corp ). Istoricul strat peste strat: `source=` cere seria unei surse anume, iar `include_legacy=true` adaugă blocul `legacy` cu seria legacy ( alt punct de măsurare: `level_cm` cum îl publică sursa, `level_cm_aligned` adus pe cota zero a stației naționale când datumul e cunoscut ). Seriile nu se amestecă în `data`.

    Parametri

    • slug*path
    • sourcequery
    • include_legacyquery
    • fromquery
    • toquery
    • intervalquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/observations"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/observations')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/observations", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/percentilePercentila zilei față de aceeași zi din ultimii 30 de ani10/min

    Nivelul ultimei zile ( prima citire a zilei locale, sursa de referință ) raportat la aceeași zi calendaristică din ultimii 30 de ani. `percentile` e 0…100, `category` una din very_low / low / normal / high / very_high; sub 10 ani de referință, `percentile` e null. O singură interogare pe fereastra de ani, nu una per zi.

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/percentile"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/percentile')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/percentile", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/recordsRecorduri istorice10/min

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/records"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/records')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/records", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/same-dayAceeași zi în anii trecuți10/min

    Parametri

    • slug*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/same-day"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/same-day')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/same-day", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/stations/{slug}/winterFenomenele de iarnă și grosimea gheții

    Observațiile de iarnă publicate pentru stație, cele mai noi primele: textul fenomenului și/sau grosimea gheții în cm. Fără observații, lista e goală.

    Parametri

    • slug*path
    • limitquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/stations/budapest/winter"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/stations/budapest/winter')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/stations/budapest/winter", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/summary/low-waterApe mici: zile consecutive sub LDC, pe sectoare, cu istoric și comparație

    Seceta hidrologică pe Dunăre, pe sectoare ( țările fluviului, de la amonte la aval ): pentru anul ales, cea mai lungă perioadă neîntreruptă sub LDC a unei stații din sector, stația record, câte stații au avut ape mici, zilele-stație sub LDC, istoricul sectorului și comparația cu anii de referință 2003, 2015, 2018 și 2022. Aceleași reguli ca fila „Ape mici” din `/{lang}/statistics`: pragurile se judecă pe citirea de referință din rollup, iar o zi lipsă rupe perioada.

    Parametri

    • yearquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/summary/low-water"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/summary/low-water')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/summary/low-water", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/summary/todaySituația azi pe țări: sub/peste prag, tendințe, prognoze, abateri de la normal, ce se schimbă azi

    Agregatul zilei, pe fiecare țară: câte stații sunt sub LDC și peste HDC ( cu procentul din stațiile cu praguri ), câte n-au citire în ultimele 48 h, tendința din 24 h ( crește / scade / stabil ) și prognoza următoarelor 24–72 h. D2 adaugă abaterea de la normalul zilei ( climatologia D1 ): câte stații sunt peste p75, sub p25 ori în intervalul normal și clasamentul celor mai mari abateri standardizate. F4 adaugă „ce se schimbă azi”: primele schimbări semnificative din variația pe 24 h, din unda Q74 ( timpul de propagare amonte → aval ) și din abaterea D2, pe bazin ( `changes` ) și pe țară ( `changes_by_country` ). Aceleași reguli ca pagina `/{lang}/today`: pragurile se judecă pe citirea de referință proaspătă, iar prognoza vine dintr-o singură emisiune.

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/summary/today"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/summary/today')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/summary/today", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Râuri și țări

  • GET/api/v1/countriesȚările din bazin
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/countries"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/countries')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/countries", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/riversRâurile din bazin și numărul de stații
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/rivers"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/rivers')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/rivers", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/rivers/{rau}Graful râului: vărsare, afluenți, țări

    Parametri

    • rau*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/rivers/sava"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/rivers/sava')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/rivers/sava", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/countriesȚările bazinului, paginat cursor ( v2 )

    Țările din registrul bazinului, cu numele pe limbile produsului; cursorul e codul ISO.

    Parametri

    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/countries"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/countries')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/countries", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/riversRâurile bazinului, paginat cursor ( v2 )

    Râurile din registrul stațiilor, cu numărul de stații pe țară. Cursorul e codul normalizat al râului; `fields=` și `format=json|csv|geojson` se aplică la fel pe toate listele v2.

    Parametri

    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/rivers"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/rivers')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/rivers", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Exporturi

  • GET/api/v1/export/country/{cod}Export CSV/JSON pe țară10/min

    Parametri

    • cod*path
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/export/country/HU"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/export/country/HU')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/export/country/HU", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Exportul poartă și el `_attribution`, cu licența în `_attribution.license` (CC BY 4.0); afișează `_attribution.source`, `_attribution.url` și licența lîngă fișier.

  • GET/api/v1/export/dailyExport open-data zilnic CSV/JSON pe țară10/min

    Fișierul zilei precedente pentru o țară din bazin, cu licență CC BY 4.0 și atribuire. CSV-ul le pune în antetele `Link`, `X-Attribution*` și `X-License*`; JSON-ul, în `_attribution` ( inclusiv `license` ). Răspunsul e cacheabil: `ETag`, `Last-Modified`, `Cache-Control`, iar `If-None-Match` întoarce 304 cu aceleași antete.

    Parametri

    • country*query
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/export/daily?country=HU"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/export/daily?country=HU')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/export/daily?country=HU", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Exportul poartă și el `_attribution`, cu licența în `_attribution.license` (CC BY 4.0); afișează `_attribution.source`, `_attribution.url` și licența lîngă fișier.

  • GET/api/v1/export/rangeExport pe interval mare, pentru cercetători ( CSV / Parquet, paginat )10/min

    O pagină de rollup zilnic (`readings_daily`) pe intervalul `from`–`to`, numai din sursele cu licență explicită de redistribuire ( registrul Q90 al licențelor ). Fiecare rând are coloana `license` a sursei; atribuirea completă și URL-ul termenilor sunt în manifestul `/export/range/licenses` și în antetele `X-License` / `X-Attribution` / `Link`. Paginarea se face cu `cursor` ( `X-Next-Cursor`, `Link: rel="next"` ), legat de filtre printr-o amprentă: două pagini consecutive nu repetă și nu sar rânduri. Fără cheie: cel mult 366 de zile și 500 de rânduri pe pagină; cu cheie (`Authorization: Bearer`): 20 de ani și 5 000 de rânduri pe pagină. Exportul e endpoint greu ( 10 cereri/minut ).

    Parametri

    • from*query
    • to*query
    • countryquery
    • formatquery
    • limitquery
    • cursorquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/export/range?from=2026-01-01&to=2026-10-23"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/export/range?from=2026-01-01&to=2026-10-23')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/export/range?from=2026-01-01&to=2026-10-23", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Exportul poartă și el `_attribution`, cu licența în `_attribution.license` (CC BY 4.0); afișează `_attribution.source`, `_attribution.url` și licența lîngă fișier.

  • GET/api/v1/export/range/licensesLicențele și atribuirile surselor exportului pe interval

    Manifestul surselor care pot apărea în `GET /export/range`: numai cele cu licență explicită de redistribuire, fiecare cu instituția, licența, URL-ul termenilor, atribuirea, transformarea făcută ( agregat zilnic ) și data verificării. O sursă refuzată sau necunoscută nu apare în manifest și nu se exportă.

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/export/range/licenses"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/export/range/licenses')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/export/range/licenses", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Exportul poartă și el `_attribution`, cu licența în `_attribution.license` (CC BY 4.0); afișează `_attribution.source`, `_attribution.url` și licența lîngă fișier.

  • GET/api/v1/export/river/{rau}Export CSV/JSON pe râu10/min

    Parametri

    • rau*path
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/export/river/sava"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/export/river/sava')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/export/river/sava", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Rută grea: 10 cereri/minut, chiar și cu o cheie.

    Exportul poartă și el `_attribution`, cu licența în `_attribution.license` (CC BY 4.0); afișează `_attribution.source`, `_attribution.url` și licența lîngă fișier.

Praguri, navigație, buletine

  • GET/api/v1/bulletinsBuletine hidrologice pe țară

    Parametri

    • countryquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/bulletins"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/bulletins')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/bulletins", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/navigationPuncte critice și restricții de navigație

    Doar rândurile active; restricțiile expirate ( `data_end` trecut ) nu se mai întorc, iar restricțiile vin numai din sursele oficiale păstrate. Răspunsul e sortat după rkm.

    Parametri

    • riverquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/navigation"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/navigation')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/navigation", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/thresholdsPraguri oficiale (LDC/HDC, RNW/HSW, apărare)

    Doar pragurile active ( valorile de arhivă rămân în platformă, cu `activ: false`, și nu se publică ). `station` e slugul stației; un slug necunoscut dă 404.

    Parametri

    • stationquery
    • pagequery
    • limitquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/thresholds"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/thresholds')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/thresholds", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/bulletinsBuletinele hidrologice, paginat cursor ( v2 )

    Buletinele naționale, cele mai noi întâi; `country` filtrează, cursorul e id-ul buletinului.

    Parametri

    • countryquery
    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/bulletins"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/bulletins')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/bulletins", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/navigationNavigația, listă unitară paginată ( v2 )

    Punctele critice și restricțiile active într-o singură listă, fiecare rând cu `kind` (`punct_critic` sau `restrictie` ); cursorul compune `kind:id`. Geometria există pe puncte.

    Parametri

    • riverquery
    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/navigation"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/navigation')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/navigation", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/thresholdsPragurile oficiale, paginat cursor ( v2 )

    Pragurile active, cu `station` ( slug ) ca filtru; cursorul e id-ul pragului. Un slug necunoscut dă 404, ca la v1.

    Parametri

    • stationquery
    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/thresholds"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/thresholds')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/thresholds", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Episoade de alertă

  • GET/api/v1/episodesEpisoade publice LDC/HDC

    Parametri

    • countryquery
    • typequery
    • limitquery
    • next_cursorquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/episodes"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/episodes')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/episodes", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/episodes/{id}Un episod de alertă

    Parametri

    • id*path
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/episodes/1"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/episodes/1')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/episodes/1", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

GeoJSON

  • GET/api/v1/geojson/riversLinia Dunării navigabile + Sava/Tisa
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/geojson/rivers"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/geojson/rivers')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/geojson/rivers", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/geojson/stationsFeatureCollection cu stațiile ( paritate export.geojson legacy )

    Parametri

    • countryquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/geojson/stations"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/geojson/stations')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/geojson/stations", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Surse și calitatea datelor

  • GET/api/v1/meta/availabilityDisponibilitatea lunară pe sursă (12 luni): zilele cu date, procentul și rulările recente

    Raportul public „transparența datelor”: câte o lună pe sursă, pe ultimele 12 luni calendaristice, cu zilele socotite (`days`, luna curentă doar până ieri), zilele cu cel puțin o citire (`days_with_data`) și procentul lor. `last_7_days` dă rulările și eșecurile ultimelor 7 zile din jurnalul Q62 (`runs` / `failures`; `null` = fără jurnal). Doar cifre: fără mesaje de eroare, fără URL-uri, fără detalii de stație. Fără rollup-ul zilnic (instanță fără ingest) `sources` e gol, nu „0 %”.

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/meta/availability"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/meta/availability')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/meta/availability", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/meta/healthSănătatea surselor
    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/meta/health"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/meta/health')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/meta/health", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/meta/qualityCalitatea datelor pe stație: citiri suspecte și starea sursei

    Agregat pe stație: numărul de citiri suspecte ( abatere peste prag față de mediana vecinilor ±6 h ), ultima citire și starea sursei care a adus-o ( `source_state`: `ok`, `eroare`, `stale` — „fără citiri în termen” ).

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/meta/quality"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/meta/quality')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/meta/quality", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v1/meta/sourcesUltima actualizare, scrierile din 24 h și calitatea în timp per sursă de crawl

    Câte un rând per sursă de crawl: ultima rulare reușită, starea ei, SLA-ul, **ultima scriere**, **rândurile citite și citirile scrise în ultimele 24 h**, **uptime pe 7 și 30 de zile**, **întârzierea medie** a datelor (vârsta medie a celei mai proaspete citiri, pe 7 zile) și **ultima eroare** (păstrată și după revenirea sursei). `stare` poate fi `cazuta` când sursa n-a mai scris nimic de peste 2 × intervalul ei, iar `eroare` înseamnă că ultima rulare a picat **și** datele de dinainte au ieșit din SLA-ul sursei; o cădere de rețea cât timp datele sunt încă în termen lasă `stare` neschimbată (eroarea rămâne în `ultima_eroare`). `uptime_7d` / `uptime_30d` sunt fracții 0–1; `null` = fereastra nu se poate calcula sau `readings` nu e disponibil acum, nu „sursă perfectă”.

    curl
    curl -sS "https://danubealert.arcm.ro/api/v1/meta/sources"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v1/meta/sources')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v1/meta/sources", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

  • GET/api/v2/meta/sourcesSursele de crawl, paginat cursor ( v2 )

    Ultima rulare și calitatea în timp per sursă; cursorul e codul sursei. Câmpurile sunt cele din `/v1/meta/sources`.

    Parametri

    • limitquery
    • next_cursorquery
    • fieldsquery
    • formatquery
    curl
    curl -sS "https://danubealert.arcm.ro/api/v2/meta/sources"
    JavaScript
    const r = await fetch('https://danubealert.arcm.ro/api/v2/meta/sources')
    if (!r.ok) throw new Error(`HTTP ${r.status}`)
    const body = await r.json()
    console.log(body)
    console.log(body._attribution.source, body._attribution.url)
    Python
    import requests
    
    r = requests.get("https://danubealert.arcm.ro/api/v2/meta/sources", timeout=30)
    r.raise_for_status()
    body = r.json()
    print(body)
    print(body["_attribution"]["source"], body["_attribution"]["url"])

    Limită de rată: Anonim: 60 cereri/minut (fereastră glisantă); cu `Authorization: Bearer <cheie>`: 600/minut.

    Răspunsul poartă `_attribution`; afișează `_attribution.source` și `_attribution.url` lîngă date.

Limite de cereri

Fereastră glisantă de 60 s; seria de citiri e un endpoint greu (10 pe minut). Peste limită: 429 cu retry_after_seconds în corp și antetele Retry-After și X-RateLimit-*. Cererile refuzate nu consumă din fereastra următoare.

Limite de cereri
AntetCe înseamnă
X-RateLimit-Limit60 / 600 / 3000 / 10
X-RateLimit-Remaining0 … limit
Retry-Afters ( 429 )
429 · retry_after_secondsJSON

Client TypeScript tipat

Tipuri generate direct din contract — fiecare rută, parametru și răspuns, fără modele scrise de mână.

TypeScript
npx openapi-typescript https://danubealert.arcm.ro/api/v1/openapi.json -o danubealert.d.ts

import type { paths } from './danubealert'
type Observatii = paths['/stations/{slug}/observations']['get']['responses']['200']['content']['application/json']

Export open-data

Fișierele zilei precedente, câte un rând pe stație, pentru fiecare țară a bazinului, în CSV sau JSON. Răspunsurile se pot păstra în cache (ETag, Last-Modified, Cache-Control); licența și atribuirea sunt în antetele fișierului și în blocul _attribution al JSON-ului.

Licență: Creative Commons Attribution 4.0 International · Atribuire: DanubeAlert și serviciile hidrologice naționale · Ziua precedentă, în fusul orar al țării.

Configuratorul de widget

Nivelul unei stații direct pe site-ul tău: alege stația, tema, limba și brandingul, vezi widgetul în timp real și copiază codul iframe în orice CMS.

Widget-urile tale, în trei pași

Alege tipul și setările — previzualizarea și snippet-ul se actualizează pe loc.

Tema
Mărime

Previzualizare ( miniatură )

Snippet-ul de inserat

<iframe
  src="https://danubealert.arcm.ro/embed/v1/station?slug=achleiten&theme=auto&lang=ro&accent=00BABE"
  title="Danube water level — Achleiten"
  width="100%"
  height="300"
  style="border:0;max-width:640px;"
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
></iframe>

Contractul complet: /api/v1/openapi.json · /api/v1/openapi.json · Datele: serviciile hidrologice naționale, prin DanubeAlert