{"openapi":"3.1.0","info":{"title":"DanubeAlert API","version":"2.0.0","license":{"name":"CC BY 4.0 pentru exporturile open-data; datele © DanubeAlert și sursele naționale citate în _attribution","url":"https://creativecommons.org/licenses/by/4.0/"},"summary":"Nivelul apei Dunării: stații, măsurători, prognoze, episoade publice; v2 cu listă unitară.","description":"API public de citire. Anonim: 60 cereri/minut ( burst 120 ), exporturile grele 10/minut; cu cheie: 600/minut la nivelul gratuit, iar nivelul profesional are plafonul lui ( îl publică `X-RateLimit-Limit` ). Cheile se creează self-service din contul gratuit ( panoul Developers ) și se trimit ca `Authorization: Bearer da_live_…`; fără antet, cererea e anonimă. O cheie malformată, necunoscută sau revocată primește 401 cu `WWW-Authenticate` ( nu trece drept anonimă ). Răspunsurile poartă blocul `_attribution` — sursa instituțională și `data_updated_at`; integratorii o afișează. D1/D2 adaugă climatologia zilei și abaterea de la normal ( blocul `anomaly` al fișei stației, `/stations/{slug}/climatology`, `/summary/today` ); F4 adaugă „ce se schimbă azi” în `/summary/today` ( `changes`, `changes_by_country`: variația pe 24 h, unda Q74 și abaterea D2 ); H3 adaugă raportul zilei ca un singur obiect în `/report/today` ( starea pe bazin, schimbările F4, stațiile sub/peste praguri și prognoza 24–72 h din G2 ); D4, transparența lunară a surselor ( `/meta/availability` ); D6, exportul pe interval pentru cercetători ( `/export/range`, cu licențele în `/export/range/licenses` ); H4, blocul `quality` al fiecărei stații ( sursa de referință, ultima citire, starea G3 și reperul cotei zero a stației ). `/v2` ( Q35 ) păstrează resursele `/v1` și adaugă pe fiecare listă paginare cursor, `fields=`, `format=json|csv|geojson` și validare `ETag` / `If-None-Match` ( 304 ). `DepreciereaBreaking` intră pe `/v3` cu anunț de minim 12 luni ( §10 ).","x-documentation-language":"ro","x-documentation-languages":{"ro":"/api/v1/openapi.json","en":"/api/v1/openapi.en.json","de":"/api/v1/openapi.de.json","hu":"/api/v1/openapi.hu.json","sr":"/api/v1/openapi.sr.json"}},"servers":[{"url":"https://danubealert.arcm.ro/api/v1","description":"Producție"}],"tags":[{"name":"stations","description":"Stații hidrologice, seriile lor de măsurători ( nivel în cm ) și climatologia zilei."},{"name":"countries","description":"Liste pe țară ( AT, SK, HU, HR, RS, BG, RO )."},{"name":"episodes","description":"Episoade de alertă publică LDC/HDC ( sensul B )."},{"name":"exports","description":"Exporturi: paritate legacy ( GeoJSON ), open-data zilnic ( CSV/JSON ) și intervalul pentru cercetători ( CSV/Parquet, cu licențele fiecărei surse )."},{"name":"meta","description":"Meta-informații: sursele, calitatea lor în timp și disponibilitatea lunară."},{"name":"summary","description":"Sinteze gata de afișat: starea de azi pe țări, cu praguri, tendințe, prognoze, abateri de la normal și ce se schimbă azi ( mișcarea pe 24 h, unda Q74, abaterea D2 ), plus raportul zilei ca un singur obiect ( starea pe bazin, pragurile, prognoza 24–72 h )."},{"name":"alerts","description":"Alerte: confirmarea pe email a unei alerte sau a unui raport zilnic, pentru conturile care nu și-au dovedit încă adresa. Alertele se creează pe site, dintr-un cont DanubeAlert."}],"paths":{"/stations":{"get":{"tags":["stations"],"operationId":"listStations","parameters":[{"name":"country","in":"query","schema":{"type":"string","enum":["AT","SK","HU","HR","RS","BG","RO"]},"description":"Codul ISO al țării."},{"name":"river","in":"query","schema":{"type":"string","default":"dunarea"},"description":"Râul normalizat (implicit `dunarea`); `all` = tot bazinul, inclusiv afluenții."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Căutare după nume sau slug."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100},"description":"Maxim 100 anonim ( 500 cu cheie, pe rutele marcate )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Paginare cursor din răspunsul anterior."},{"name":"sort","in":"query","schema":{"type":"string","enum":["rkm"]},"description":"`rkm` = de la izvor la vărsare ( kilometraj descrescător, stațiile fără kilometraj la urmă ). Nu se combină cu `next_cursor`."}],"responses":{"200":{"$ref":"#/components/responses/ListaStatii"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Lista stațiilor","description":"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 )."}},"/rivers":{"get":{"tags":["stations"],"operationId":"listRivers","responses":{"200":{"$ref":"#/components/responses/Rauri"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Râurile din bazin și numărul de stații","description":"Râurile din bazin și numărul de stații"}},"/measurements":{"get":{"tags":["stations"],"operationId":"getMeasurements","parameters":[{"name":"station","in":"query","required":true,"schema":{"type":"string"}},{"name":"measure","in":"query","schema":{"type":"string","enum":["water_temperature_c","discharge_m3s","air_temperature_c","wind_ms","precipitation_mm"]}},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Seria de măsurători","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Masuratori"}}}},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Temperatura apei, debit, temperatura aerului","description":"Temperatura apei, debit, temperatura aerului"}},"/wizard":{"get":{"tags":["stations"],"operationId":"wizardData","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Căutare după nume de stație sau de râu; diacriticele și chirilica sunt tolerate."},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":50},"description":"Câte rezultate pe listă, la căutare ( 1…50 )."},{"name":"parte","in":"query","schema":{"type":"string","enum":["sectoare","tari"]},"description":"Doar sectoarele Dunării sau doar țările ( cu numărul de râuri și de stații )."},{"name":"tara","in":"query","schema":{"type":"string","pattern":"^[A-Za-z]{2}$"},"description":"O singură țară ( cod ISO ), cu râurile și stațiile ei."},{"name":"lang","in":"query","schema":{"type":"string","default":"en"},"description":"Limba numelor de țări și de râuri."}],"responses":{"200":{"description":"Structura asistentului ( sectoare, țări, râuri ) sau rezultatele căutării"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Datele asistentului de alerte: sectoare, țări, râuri și căutare","description":"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."}},"/countries":{"get":{"tags":["meta"],"operationId":"listCountries","responses":{"200":{"description":"Lista țărilor"}},"summary":"Țările din bazin","description":"Țările din bazin"}},"/meta/health":{"get":{"tags":["meta"],"operationId":"metaHealth","responses":{"200":{"description":"Starea surselor"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Sănătatea surselor","description":"Sănătatea surselor"}},"/stations/{slug}/records":{"get":{"tags":["stations"],"operationId":"stationRecords","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Recorduri"},"404":{"$ref":"#/components/responses/Negasit"}},"summary":"Recorduri istorice","description":"Recorduri istorice"}},"/stations/{slug}/same-day":{"get":{"tags":["stations"],"operationId":"stationSameDay","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Seria"},"404":{"$ref":"#/components/responses/Negasit"}},"summary":"Aceeași zi în anii trecuți","description":"Aceeași zi în anii trecuți"}},"/stations/{slug}/percentile":{"get":{"tags":["stations"],"operationId":"stationPercentile","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Percentila zilei"},"404":{"$ref":"#/components/responses/Negasit"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Percentila zilei față de aceeași zi din ultimii 30 de ani","description":"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."}},"/stations/{slug}/climatology":{"get":{"tags":["stations"],"operationId":"stationClimatology","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"day","in":"query","schema":{"type":"string","pattern":"^\\d{2}-\\d{2}$"},"description":"Ziua calendaristică `MM-DD` ( 29 februarie acceptat ); lipsă = toate zilele anului."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":366,"default":366},"description":"Câte zile calendaristice se întorc, în ordine."}],"responses":{"200":{"$ref":"#/components/responses/Climatologie"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"500":{"description":"Citirea din tabela materializată a eșuat ( altă eroare decât tabela lipsă, care dă 503 ).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Eroare"}}}},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Climatologia zilei: media și percentilele din tot istoricul","description":"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`."}},"/stations/{slug}/events":{"get":{"tags":["stations"],"operationId":"stationEvents","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"tip","in":"query","schema":{"type":"string","enum":["viitura","seceta"]},"description":"Doar evenimentele de tipul cerut; lipsă = viituri și secete."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Câte evenimente se întorc, cele mai noi primele."}],"responses":{"200":{"$ref":"#/components/responses/Evenimente"},"400":{"$ref":"#/components/responses/EroareCerere"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Evenimentele istorice ale stației: viituri și secete majore","description":"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."}},"/export/country/{cod}":{"get":{"tags":["exports"],"operationId":"exportCountry","parameters":[{"name":"cod","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","json"]}}],"responses":{"200":{"description":"Seriile zilnice"},"400":{"$ref":"#/components/responses/EroareCerere"},"404":{"$ref":"#/components/responses/Negasit"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Export CSV/JSON pe țară","description":"Export CSV/JSON pe țară"}},"/export/river/{rau}":{"get":{"tags":["exports"],"operationId":"exportRiver","parameters":[{"name":"rau","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","json"]}}],"responses":{"200":{"description":"Seriile zilnice"},"400":{"$ref":"#/components/responses/EroareCerere"},"404":{"$ref":"#/components/responses/Negasit"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Export CSV/JSON pe râu","description":"Export CSV/JSON pe râu"}},"/export/daily":{"get":{"tags":["exports"],"operationId":"exportDaily","parameters":[{"name":"country","in":"query","required":true,"schema":{"type":"string"},"description":"Codul ISO 3166-1 alpha-2 al țării ( AT, SK, HU, HR, RS, BG, RO… )."},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","json"],"default":"json"}}],"responses":{"200":{"description":"Exportul zilei precedente, cu licență și atribuire.","content":{"application/json":{"schema":{"type":"object","properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"}}}},"text/csv":{"schema":{"type":"string"}}}},"304":{"description":"Nemodificat ( `If-None-Match` / `If-Modified-Since` ); antetele de licență și atribuire rămân."},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Export open-data zilnic CSV/JSON pe țară","description":"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."}},"/export/range":{"get":{"tags":["exports"],"operationId":"exportRange","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Prima zi a intervalului ( YYYY-MM-DD )."},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Ultima zi a intervalului, inclusiv ( YYYY-MM-DD )."},{"name":"country","in":"query","schema":{"type":"string"},"description":"Codul ISO al țării; lipsă = tot bazinul."},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","parquet"],"default":"csv"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":5000},"description":"Rânduri pe pagină ( 500 anonim / 5 000 cu cheie )."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac primit în `X-Next-Cursor`; lipsește la prima pagină."}],"responses":{"200":{"description":"O pagină de export, cu licența fiecărui rând și atribuirea în antete.","headers":{"X-Export-From":{"description":"Prima zi a intervalului cerut ( `YYYY-MM-DD` ).","schema":{"type":"string","format":"date"}},"X-Export-To":{"description":"Ultima zi a intervalului cerut, inclusiv ( `YYYY-MM-DD` ).","schema":{"type":"string","format":"date"}},"X-Export-Page":{"description":"Numărul paginii, de la 1.","schema":{"type":"integer"}},"X-Export-Rows":{"description":"Câte rânduri are pagina; `0` pe 204.","schema":{"type":"integer"}},"X-Next-Cursor":{"description":"Cursorul opac al paginii următoare; lipsește pe ultima pagină.","schema":{"type":"string"}},"Link":{"description":"`rel=\"next\"` ( pagina următoare ), `rel=\"describedby\"` ( manifestul `/export/range/licenses` ), `rel=\"license\"` și `rel=\"about\"`.","schema":{"type":"string"}},"X-License":{"description":"Identificatorii licențelor surselor din pagină, despărțiți prin virgulă ( registrul Q90 ).","schema":{"type":"string"}},"X-Attribution":{"description":"Textul de atribuire al surselor din pagină, cu identificatorii lor.","schema":{"type":"string"}},"X-Attribution-Url":{"description":"Pagina publică „About”, cu sursele și licențele lor.","schema":{"type":"string","format":"uri"}},"Content-Disposition":{"description":"Numele fișierului descărcat, derivat din interval și pagină.","schema":{"type":"string"}}},"content":{"text/csv":{"schema":{"type":"string"}},"application/vnd.apache.parquet":{"schema":{"type":"string","format":"binary"}}}},"204":{"description":"Intervalul nu are rânduri: fără fișier gol, cu licențele în antete.","headers":{"X-Export-From":{"description":"Prima zi a intervalului cerut ( `YYYY-MM-DD` ).","schema":{"type":"string","format":"date"}},"X-Export-To":{"description":"Ultima zi a intervalului cerut, inclusiv ( `YYYY-MM-DD` ).","schema":{"type":"string","format":"date"}},"X-Export-Page":{"description":"Numărul paginii, de la 1.","schema":{"type":"integer"}},"X-Export-Rows":{"description":"Câte rânduri are pagina; `0` pe 204.","schema":{"type":"integer"}},"X-License":{"description":"Identificatorii licențelor surselor din pagină, despărțiți prin virgulă ( registrul Q90 ).","schema":{"type":"string"}},"X-Attribution":{"description":"Textul de atribuire al surselor din pagină, cu identificatorii lor.","schema":{"type":"string"}},"X-Attribution-Url":{"description":"Pagina publică „About”, cu sursele și licențele lor.","schema":{"type":"string","format":"uri"}}}},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"500":{"description":"Citirea din rollup sau serializarea paginii a eșuat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Eroare"}}}},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Export pe interval mare, pentru cercetători ( CSV / Parquet, paginat )","description":"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 )."}},"/export/range/licenses":{"get":{"tags":["exports"],"operationId":"exportRangeLicenses","responses":{"200":{"description":"Licențele surselor permise, cu atribuirea și dovada verificării.","headers":{"X-License":{"description":"Identificatorii licențelor surselor din pagină, despărțiți prin virgulă ( registrul Q90 ).","schema":{"type":"string"}},"X-Attribution":{"description":"Textul de atribuire al surselor din pagină, cu identificatorii lor.","schema":{"type":"string"}},"X-Attribution-Url":{"description":"Pagina publică „About”, cu sursele și licențele lor.","schema":{"type":"string","format":"uri"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenteExport"}}}},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Licențele și atribuirile surselor exportului pe interval","description":"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ă."}},"/thresholds":{"get":{"tags":["meta"],"operationId":"listThresholds","parameters":[{"name":"station","in":"query","schema":{"type":"string"},"description":"Slugul stației; lipsă = toate pragurile active."},{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1},"description":"Pagina ( de la 1 )."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."}],"responses":{"200":{"$ref":"#/components/responses/Praguri"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Praguri oficiale (LDC/HDC, RNW/HSW, apărare)","description":"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."}},"/navigation":{"get":{"tags":["meta"],"operationId":"getNavigation","parameters":[{"name":"river","in":"query","schema":{"type":"string"},"description":"Codul râului normalizat (ex. `dunarea`); lipsă sau `all` = tot bazinul."}],"responses":{"200":{"$ref":"#/components/responses/Navigatie"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Puncte critice și restricții de navigație","description":"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."}},"/bulletins":{"get":{"tags":["meta"],"operationId":"listBulletins","parameters":[{"name":"country","in":"query","schema":{"type":"string"},"description":"Cod ISO opțional (RO, HU, RS, HR, SK, BG, DE, AT, SI, BA, CZ, MD, UA)."}],"responses":{"200":{"description":"Lista buletinelor, cele mai noi întâi."},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Buletine hidrologice pe țară","description":"Buletine hidrologice pe țară"}},"/stations/{slug}":{"get":{"tags":["stations"],"operationId":"getStation","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"example":"budapest"}],"responses":{"200":{"$ref":"#/components/responses/Statie"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Stația și pragurile LDC/HDC","description":"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 )."}},"/stations/{slug}/observations":{"get":{"tags":["stations"],"operationId":"getObservations","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string","example":"danubeportal"},"description":"Seria unei singure surse ( `readings.source`: afdj, vizugy, doris, danubeportal… ); `danubeportal` include istoricul legacy. Implicit: sursa de referință. Necunoscută → 400 `invalid_source`."},{"name":"include_legacy","in":"query","schema":{"type":"boolean","default":false},"description":"Adaugă blocul `legacy` ( doar JSON; cu `format=csv` → 400 ). `legacy` e `null` când referința e chiar DanubePortal ( fără sursă națională )."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO 8601 UTC inclusiv."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","schema":{"type":"string","enum":["raw","hourly","daily"],"default":"raw"},"description":"Agregat orar/zilnic din rollup-ul platformei."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"`csv` întoarce `text/csv` cu antetul `observed_at,level_cm` și `Content-Disposition: attachment`."}],"responses":{"200":{"$ref":"#/components/responses/Masuratori"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Serie de măsurători ( nivel în cm )","description":"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`."}},"/stations/{slug}/discharge":{"get":{"tags":["stations"],"operationId":"getStationDischarge","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"example":"budapest"},{"name":"source","in":"query","schema":{"type":"string","example":"vizugy"},"description":"Seria unei singure surse ( `masuratori.source`: bafu, vizugy, noe, hnd-bayern, pegelonline… ). Implicit: sursa celei mai noi măsurători de debit. Necunoscută → 400 `invalid_source`."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO 8601 UTC inclusiv; implicit acum − 30 zile."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO 8601 UTC inclusiv; implicit acum."},{"name":"interval","in":"query","schema":{"type":"string","enum":["raw","hourly","daily"],"default":"raw"}},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"`csv` întoarce `text/csv` cu antetul `observed_at,discharge_m3s`."}],"responses":{"200":{"$ref":"#/components/responses/Debit"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Seria de debit ( Q, m³/s ) a stației","description":"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."}},"/stations/{slug}/winter":{"get":{"tags":["stations"],"operationId":"getStationWinter","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Câte observații ( maxim 200 )."}],"responses":{"200":{"description":"Observațiile de iarnă ale stației","content":{"application/json":{"schema":{"type":"object","properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"},"data":{"type":"array","items":{"type":"object","properties":{"station_slug":{"type":"string"},"observed_at":{"type":"string","nullable":true},"phenomenon":{"type":"string","nullable":true},"ice_thickness_cm":{"type":"integer","nullable":true},"source":{"type":"string","nullable":true},"source_station_id":{"type":"string","nullable":true}}}},"meta":{"type":"object","properties":{"totalDocs":{"type":"integer"},"limit":{"type":"integer"}}}}}}}},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Fenomenele de iarnă și grosimea gheții","description":"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ă."}},"/stations/{slug}/ice":{"get":{"tags":["stations"],"operationId":"getStationIce","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"example":"bratislava"},{"name":"limit","in":"query","schema":{"type":"integer","default":90,"minimum":1,"maximum":366},"description":"Câte zile ( maxim 366 )."},{"name":"from","in":"query","schema":{"type":"string","format":"date"},"description":"Ziua ISO de la care se citește ( inclusiv )."},{"name":"to","in":"query","schema":{"type":"string","format":"date"},"description":"Ziua ISO până la care se citește ( inclusiv )."}],"responses":{"200":{"description":"Ghețurile stației, cele mai noi zile primele","content":{"application/json":{"schema":{"type":"object","properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"},"data":{"type":"array","items":{"type":"object","properties":{"station_slug":{"type":"string"},"date":{"type":"string","format":"date"},"ice":{"type":"boolean","description":"`false` când sursa a publicat indicele 0 ( fără fenomene )."},"code":{"type":"integer","nullable":true,"description":"Indicele oficial al sursei ( la SHMÚ, 0–8 ); `null` când rândul nu are detalii normalizate."},"phenomena":{"type":"array","items":{"type":"string","enum":["ice_slush","shore_ice","ice_bridge","ice_jam","ice_floe","water_over_ice"]}},"source_label":{"type":"string","nullable":true,"description":"Eticheta originală a sursei ( netradusă )."},"source":{"type":"string"},"source_station_id":{"type":"string","nullable":true},"url":{"type":"string","nullable":true}}}},"meta":{"type":"object","properties":{"totalDocs":{"type":"integer"},"limit":{"type":"integer"},"from":{"type":"string","nullable":true},"to":{"type":"string","nullable":true}}}}}}}},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Ghețurile din buletinele naționale, pe stație și zi","description":"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."}},"/observations":{"get":{"tags":["stations"],"operationId":"compareObservations","parameters":[{"name":"stations","in":"query","required":true,"schema":{"type":"string"},"description":"Listă de sluguri separate prin virgulă (maxim 6)."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO 8601 UTC inclusiv."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"interval","in":"query","schema":{"type":"string","enum":["raw","hourly","daily"],"default":"daily"}},{"name":"river","in":"query","schema":{"type":"string","default":"dunarea"},"description":"Filtru de râu; `all` = orice stație cerută."}],"responses":{"200":{"$ref":"#/components/responses/Comparatie"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Compară până la 6 stații într-un răspuns","description":"Aceleași reguli ca observațiile unei stații; `interval` implicit `daily` și rate limit „greu” (10/min)."}},"/stations/{slug}/forecast":{"get":{"tags":["stations"],"operationId":"getForecast","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Prognoza"},"404":{"$ref":"#/components/responses/Negasit"}},"summary":"Prognoza stației ( unde există )","description":"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."}},"/stations/{slug}/forecast-accuracy":{"get":{"tags":["stations"],"operationId":"stationForecastAccuracy","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Slugul stației."},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":90},"description":"Fereastra backtestului, în zile după momentul țintă."}],"responses":{"200":{"$ref":"#/components/responses/AcuratetePrognoza"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Acuratețea prognozelor stației, pe sursă și orizont","description":"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."}},"/forecast/accuracy":{"get":{"tags":["stations"],"operationId":"getForecastAccuracy","parameters":[{"name":"station","in":"query","schema":{"type":"string"},"description":"Slugul stației; fără el, tot bazinul."},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":90},"description":"Fereastra backtestului, în zile după momentul țintă."}],"responses":{"200":{"$ref":"#/components/responses/AcuratetePrognoza"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Acuratețea prognozelor oficiale față de citirile reale, pe sursă și orizont","description":"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."}},"/countries/{code}/stations":{"get":{"tags":["countries"],"operationId":"listCountryStations","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","enum":["AT","SK","HU","HR","RS","BG","RO"]}}],"responses":{"200":{"$ref":"#/components/responses/ListaStatii"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Stațiile unei țări","description":"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 )."}},"/stations/{slug}/neighbors":{"get":{"tags":["stations"],"operationId":"stationNeighbors","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Vecinii stației"},"404":{"$ref":"#/components/responses/Negasit"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Vecinii amonte/aval și confluențele","description":"Vecinii amonte/aval și confluențele"}},"/rivers/{rau}":{"get":{"tags":["meta"],"operationId":"riverGraph","parameters":[{"name":"rau","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Graful râului"},"404":{"$ref":"#/components/responses/Negasit"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Graful râului: vărsare, afluenți, țări","description":"Graful râului: vărsare, afluenți, țări"}},"/episodes":{"get":{"tags":["episodes"],"operationId":"listEpisodes","parameters":[{"name":"country","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string","enum":["ldc","hdc"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"next_cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Episoade"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Episoade publice LDC/HDC","description":"Episoade publice LDC/HDC"}},"/episodes/{id}":{"get":{"tags":["episodes"],"operationId":"getEpisode","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#/components/responses/Episod"},"404":{"$ref":"#/components/responses/Negasit"}},"summary":"Un episod de alertă","description":"Un episod de alertă"}},"/geojson/rivers":{"get":{"tags":["exports"],"operationId":"geojsonRivers","responses":{"200":{"description":"FeatureCollection Natural Earth"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Linia Dunării navigabile + Sava/Tisa","description":"Linia Dunării navigabile + Sava/Tisa"}},"/geojson/stations":{"get":{"tags":["exports"],"operationId":"geojsonStations","parameters":[{"name":"country","in":"query","schema":{"type":"string"},"description":"Filtru ISO; fără = tot coridorul."}],"responses":{"200":{"description":"GeoJSON FeatureCollection","content":{"application/geo+json":{"schema":{"type":"object","properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"}}}}}},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"FeatureCollection cu stațiile ( paritate export.geojson legacy )","description":"FeatureCollection cu stațiile ( paritate export.geojson legacy )"}},"/meta/sources":{"get":{"tags":["meta"],"operationId":"metaSources","responses":{"200":{"$ref":"#/components/responses/Surse"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Ultima actualizare, scrierile din 24 h și calitatea în timp per sursă de crawl","description":"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ă”."}},"/meta/quality":{"get":{"tags":["meta"],"operationId":"metaQuality","responses":{"200":{"$ref":"#/components/responses/Calitate"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Calitatea datelor pe stație: citiri suspecte și starea sursei","description":"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” )."}},"/meta/availability":{"get":{"tags":["meta"],"operationId":"metaAvailability","responses":{"200":{"$ref":"#/components/responses/Disponibilitate"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Disponibilitatea lunară pe sursă (12 luni): zilele cu date, procentul și rulările recente","description":"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 %”."}},"/summary/today":{"get":{"tags":["summary"],"operationId":"getSummaryToday","responses":{"200":{"$ref":"#/components/responses/SituatiaAzi"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Situația azi pe țări: sub/peste prag, tendințe, prognoze, abateri de la normal, ce se schimbă azi","description":"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."}},"/report/today":{"get":{"tags":["summary"],"operationId":"getReportToday","responses":{"200":{"$ref":"#/components/responses/RaportZi"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Raportul zilei: starea pe bazin, ce se schimbă azi, stațiile sub/peste praguri, prognoza 24–72 h","description":"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."}},"/summary/low-water":{"get":{"tags":["summary"],"operationId":"getSummaryLowWater","parameters":[{"name":"year","in":"query","schema":{"type":"integer","minimum":1900,"maximum":2200},"description":"Anul cerut; lipsă = cel mai recent an cu perioade sub LDC."}],"responses":{"200":{"$ref":"#/components/responses/ApeMici"},"400":{"$ref":"#/components/responses/EroareCerere"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Ape mici: zile consecutive sub LDC, pe sectoare, cu istoric și comparație","description":"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."}},"/basin-precipitation":{"get":{"tags":["stations"],"operationId":"getBasinPrecipitation","parameters":[{"name":"station","in":"query","schema":{"type":"string"},"description":"Slugul stației din aval; doar sub-bazinele legate de ea. Un slug necunoscut dă 404."},{"name":"river","in":"query","schema":{"type":"string","enum":["inn","isar","lech","morava","vah","tisa","sava","drava","mura","bosna","vrbas","kupa","una","prut"]},"description":"Codul unui râu acoperit; un râu neacoperit dă 400."}],"responses":{"200":{"$ref":"#/components/responses/PrecipitatiiBazin"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Precipitațiile cumulate pe 24 / 72 h pe sub-bazine, cu stația din aval","description":"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`."}},"/v2/stations":{"get":{"tags":["stations"],"operationId":"listStationsV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"country","in":"query","schema":{"type":"string","enum":["AT","SK","HU","HR","RS","BG","RO"]},"description":"Codul ISO al țării."},{"name":"river","in":"query","schema":{"type":"string","default":"dunarea"},"description":"Râul normalizat ( implicit `dunarea` ); `all` = tot bazinul."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Căutare după nume sau slug."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":100},"description":"Rânduri pe pagină ( maxim 100 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Lista stațiilor ( v2, cursor + fields + format )","description":"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`."}},"/v2/rivers":{"get":{"tags":["stations"],"operationId":"listRiversV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Râurile bazinului, paginat cursor ( v2 )","description":"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."}},"/v2/countries":{"get":{"tags":["meta"],"operationId":"listCountriesV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Țările bazinului, paginat cursor ( v2 )","description":"Țările din registrul bazinului, cu numele pe limbile produsului; cursorul e codul ISO."}},"/v2/thresholds":{"get":{"tags":["meta"],"operationId":"listThresholdsV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"station","in":"query","schema":{"type":"string"},"description":"Slugul stației; lipsă = toate pragurile active."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Pragurile oficiale, paginat cursor ( v2 )","description":"Pragurile active, cu `station` ( slug ) ca filtru; cursorul e id-ul pragului. Un slug necunoscut dă 404, ca la v1."}},"/v2/bulletins":{"get":{"tags":["meta"],"operationId":"listBulletinsV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"country","in":"query","schema":{"type":"string"},"description":"Cod ISO opțional ( RO, HU, RS, HR, SK, BG, DE, AT, SI, BA, CZ, MD, UA )."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":100},"description":"Rânduri pe pagină ( maxim 100 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Buletinele hidrologice, paginat cursor ( v2 )","description":"Buletinele naționale, cele mai noi întâi; `country` filtrează, cursorul e id-ul buletinului."}},"/v2/navigation":{"get":{"tags":["meta"],"operationId":"listNavigationV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"river","in":"query","schema":{"type":"string"},"description":"Codul râului normalizat ( ex. `dunarea` ); lipsă sau `all` = tot bazinul."},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Navigația, listă unitară paginată ( v2 )","description":"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."}},"/v2/meta/sources":{"get":{"tags":["meta"],"operationId":"listMetaSourcesV2","servers":[{"url":"https://danubealert.arcm.ro/api","description":"API v2 ( rutele poartă prefixul /v2 )"}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"description":"Rânduri pe pagină ( maxim 200 )."},{"name":"next_cursor","in":"query","schema":{"type":"string"},"description":"Cursorul opac din `next_cursor` al paginii anterioare ( keyset, nu offset )."},{"name":"fields","in":"query","schema":{"type":"string"},"description":"Selecție de câmpuri separate prin virgulă ( sparse fieldset ); câmpurile necunoscute se ignoră. Fără el, rândul întreg."},{"name":"format","in":"query","schema":{"type":"string","enum":["json","csv","geojson"],"default":"json"},"description":"`json` ( implicit ), `csv` ( text/csv cu antet ) sau `geojson` ( FeatureCollection; geometrie unde resursa are coordonate )."}],"responses":{"200":{"$ref":"#/components/responses/ListaV2"},"304":{"$ref":"#/components/responses/Nemodificat"},"400":{"$ref":"#/components/responses/EroareCerere"},"401":{"$ref":"#/components/responses/CheieInvalida"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Sursele de crawl, paginat cursor ( v2 )","description":"Ultima rulare și calitatea în timp per sursă; cursorul e codul sursei. Câmpurile sunt cele din `/v1/meta/sources`."}},"/alerts/confirm":{"get":{"tags":["alerts"],"operationId":"confirmAlert","parameters":[{"name":"t","in":"query","required":true,"schema":{"type":"string"},"description":"Jetonul opac din linkul emailului."},{"name":"format","in":"query","schema":{"type":"string","enum":["json"]},"description":"`json` = răspuns pentru integratori, fără redirect."}],"responses":{"200":{"$ref":"#/components/responses/ConfirmareAlerta"},"303":{"description":"Browserul e dus la pagina de confirmare ( `/{lang}/alerts/confirm?t=…` ) sau la pagina de start pentru un jeton invalid."},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"}},"summary":"Linkul de confirmare din email ( nu pornește nimic )","description":"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."},"post":{"tags":["alerts"],"operationId":"confirmAlertPost","parameters":[{"name":"t","in":"query","schema":{"type":"string"},"description":"Jetonul opac; alternativ, în corpul JSON."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"t":{"type":"string"}}}}}},"responses":{"200":{"$ref":"#/components/responses/ConfirmareAlerta"},"401":{"$ref":"#/components/responses/CheieInvalida"},"404":{"$ref":"#/components/responses/Negasit"},"429":{"$ref":"#/components/responses/Limita"},"503":{"$ref":"#/components/responses/Indisponibil"}},"summary":"Pornește alerta sau raportul confirmat","description":"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` )."}}},"components":{"securitySchemes":{"cheie":{"type":"http","scheme":"bearer","description":"Cheie self-service din panoul Developers ( `da_live_` + 48 caractere hex ), trimisă ca `Authorization: Bearer …`: 600 de cereri pe minut la nivelul gratuit, iar nivelul profesional are plafonul lui, publicat în `RateLimit-Limit` ( și `X-RateLimit-Limit`, pentru clienții vechi ). Anonim = fără antet, 60 pe minut. O cheie malformată, necunoscută sau revocată primește 401 ( `CheieInvalida` ); revocarea are efect imediat."}},"responses":{"ListaStatii":{"description":"Lista paginată cu cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginaStatii"}}}},"Statie":{"description":"Stația cu praguri și coordonate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Statie"}}}},"Masuratori":{"description":"Serie de măsurători","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Masuratori"}}}},"Debit":{"description":"Seria de debit ( m³/s ) a stației, dintr-o singură sursă","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Debit"}},"text/csv":{"schema":{"type":"string"}}}},"Prognoza":{"description":"Prognoza disponibilă ( gol dacă sursa nu oferă )","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrognozaStatie"}}}},"AcuratetePrognoza":{"description":"Backtest pe sursă × orizont ( +24 / +48 / +72 h ): MAE, bias și procentul în banda min–max","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcuratetePrognoza"}}}},"Episoade":{"description":"Lista paginată de episoade","content":{"application/json":{"schema":{"type":"object"}}}},"Episod":{"description":"Un episod LDC/HDC","content":{"application/json":{"schema":{"type":"object"}}}},"Surse":{"description":"Ultima rulare reușită și calitatea în timp per sursă","content":{"application/json":{"schema":{"type":"object","properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SursaCalitate"}}},"required":["_attribution","data"]}}}},"Calitate":{"description":"Agregat pe stație: suspecte, ultima citire, starea sursei","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Calitate"}}}},"Disponibilitate":{"description":"Disponibilitatea lunară pe sursă, pe 12 luni; doar cifre","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Disponibilitate"}}}},"Climatologie":{"description":"Climatologia zilei pe stație: seria de referință din tot istoricul, pe fiecare zi calendaristică","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Climatologie"}}}},"Evenimente":{"description":"Evenimentele istorice ale stației, cele mai noi primele, cu atribuirea lor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvenimenteStatie"}}}},"SituatiaAzi":{"description":"Sinteza zilei pe țări, cu praguri, tendințe, prognoze și abaterile de la normalul zilei","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SituatiaAzi"}}}},"RaportZi":{"description":"Raportul zilei: starea pe bazin, schimbările F4, stațiile sub/peste praguri și prognoza 24–72 h din G2","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RaportZi"}}}},"ApeMici":{"description":"Apele mici pe sectoare: perioada record sub LDC, istoricul și anii de referință","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApeMici"}}}},"PrecipitatiiBazin":{"description":"Precipitațiile cumulate pe 24 / 72 h ale sub-bazinelor, cu stația din aval","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrecipitatiiBazin"}}}},"Praguri":{"description":"Pragurile active, paginat, cu legătura la stație","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Praguri"}}}},"Navigatie":{"description":"Puncte critice + restricții active, sortate după rkm","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Navigatie"}}}},"Comparatie":{"description":"Până la 6 stații cu seriile lor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Comparatie"}}}},"Rauri":{"description":"Râurile și numărul de stații","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Rauri"}}}},"ListaV2":{"description":"Listă v2 paginată cursor, cu selecție de câmpuri și trei reprezentări. Antetele `ETag`, `Cache-Control` și `Last-Modified` se pun pe 200 și pe 304; `If-None-Match` potrivit întoarce 304 fără corp.","headers":{"ETag":{"description":"Validatorul puternic al reprezentării; se trimite înapoi ca `If-None-Match`.","schema":{"type":"string","example":"\"AbC123…\""}},"Cache-Control":{"description":"Prospețimea listei; marginile pot servi vechiul răspuns cât îl reîmprospătează.","schema":{"type":"string","example":"public, max-age=60, stale-while-revalidate=300"}},"Last-Modified":{"description":"Cea mai nouă dată de referință din listă, când există.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginaV2"}},"text/csv":{"schema":{"type":"string"}},"application/geo+json":{"schema":{"$ref":"#/components/schemas/FeatureCollectionV2"}}}},"Nemodificat":{"description":"Nemodificat ( `If-None-Match` / `If-Modified-Since` ); corpul lipsește, antetele de validare rămân.","headers":{"ETag":{"description":"Același validator ca răspunsul 200.","schema":{"type":"string"}},"Cache-Control":{"description":"Aceeași politică de cache ca răspunsul 200.","schema":{"type":"string"}},"Last-Modified":{"description":"Aceeași dată de referință ca răspunsul 200, când există.","schema":{"type":"string"}}}},"EroareCerere":{"description":"Cerere invalidă ( query sau slug )","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Eroare"}}}},"Negasit":{"description":"Resursa nu există","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Eroare"}}}},"Indisponibil":{"description":"Serviciu temporar indisponibil ( 503 )","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Eroare"}}}},"CheieInvalida":{"description":"Cheia din `Authorization: Bearer` e malformată, necunoscută sau revocată — 401 ( decizia QA #200 ). Fără antet, cererea ar fi trecut anonim.","headers":{"WWW-Authenticate":{"description":"RFC 6750: `Bearer realm=\"DanubeAlert API v1\", error=\"invalid_token\", error_description=\"…\"`.","schema":{"type":"string","example":"Bearer realm=\"DanubeAlert API v1\", error=\"invalid_token\", error_description=\"The API key is unknown or revoked\""}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EroareCheie"}}}},"Limita":{"description":"Limita depășită — 429 cu `retry_after_seconds` ( §3 )","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secunde până la următoarea fereastră."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EroareLimita"}}}},"ConfirmareAlerta":{"description":"Rezultatul confirmării din linkul emailului","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmareAlerta"}}}}},"schemas":{"LicentaSursaExport":{"type":"object","required":["sursa","institutie","licenta","url_licenta","atribuire","verificat"],"properties":{"sursa":{"type":"string","example":"pegelonline","description":"Identificatorul din `readings.source`."},"institutie":{"type":"string","description":"Instituția care publică datele."},"tara":{"type":"string","nullable":true,"description":"Codul țării instituției; `null` pentru surse internaționale."},"licenta":{"type":"string","example":"DL-DE->Zero-2.0","description":"Identificatorul licenței ( SPDX-like )."},"nume_licenta":{"type":"string","description":"Numele complet al licenței."},"url_licenta":{"type":"string","format":"uri","description":"Pagina termenilor pe care se sprijină decizia."},"atribuire":{"type":"string","description":"Textul de atribuire cerut de sursă, gata de pus lângă fișiere."},"transformare":{"type":"string","description":"Ce s-a schimbat față de original ( agregat zilnic )."},"verificat":{"type":"string","format":"date","description":"Data la care au fost verificați termenii."}}},"LicenteExport":{"type":"object","required":["_attribution","licente"],"properties":{"_attribution":{"$ref":"#/components/schemas/Atribuire"},"licente":{"type":"array","items":{"$ref":"#/components/schemas/LicentaSursaExport"}},"nota":{"type":"string","description":"Regula de licență aplicată exportului."}}},"PrognozaOrizont":{"type":"object","description":"Un orizont al prognozei: ziua și orele de la emitere, nivelul central în cm și banda min–max publicată de sursă ( `null` unde sursa nu o dă ). `orientativ` marchează zilele 4–5 ( +96 / +120 h ): apar în date ca tendință, dar nu declanșează alerte.","properties":{"day":{"type":"integer","example":1,"description":"Ziua față de emitere ( `horizon_h` / 24 )."},"horizon_h":{"type":"integer","enum":[24,48,72,96,120]},"level_cm":{"type":"integer","example":310},"level_min_cm":{"type":"integer","nullable":true,"example":300,"description":"Marginea de jos publicată de sursă; `null` fără bandă."},"level_max_cm":{"type":"integer","nullable":true,"example":320,"description":"Marginea de sus publicată de sursă; `null` fără bandă."},"orientativ":{"type":"boolean","description":"`true` pentru zilele 4–5 ( +96 / +120 h ): informativ, fără alertă."}},"required":["day","horizon_h","level_cm","level_min_cm","level_max_cm","orientativ"]},"PrognozaStatie":{"type":"object","description":"Prognoza unei stații ( `GET /stations/{slug}/forecast` ): ultima emisiune dintr-o singură sursă, cât de departe merge ( `horizon_hours` ), orizonturile cu banda min–max și `orientativ` pe zilele 4–5. Corpul e gol ( `horizons: []`, `horizon_hours: null` ) când stația nu are încă prognoză.","properties":{"station":{"type":"string","example":"budapest","description":"Slugul stației."},"source":{"type":"string","nullable":true,"example":"afdj","description":"Emitentul ( `forecasts.source` )."},"issued_at":{"type":"string","format":"date-time","nullable":true,"description":"Momentul emiterii, ISO UTC."},"horizon_hours":{"type":"integer","enum":[24,48,72,96,120],"nullable":true,"description":"Ultimul orizont publicat, în ore ( `orizontOre` )."},"horizons":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaOrizont"}},"band":{"type":"object","description":"Banda agregată pe toată emisiunea; pe fiecare orizont, `level_min_cm` / `level_max_cm`.","properties":{"min":{"type":"integer","nullable":true},"max":{"type":"integer","nullable":true}},"required":["min","max"]},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["station","source","issued_at","horizon_hours","horizons","band","_attribution"]},"PrognozaModel":{"type":"object","description":"N77: prognoza modelului GloFAS ( setul `cems-glofas-forecast`, produsul `forecast` din `debit_model` ), arătată **separat** de prognoza oficială, doar pe stațiile fără prognoză oficială activă și cu mapare stație → celulă verificată N43 / N46. `official: false` și `label` o deosebesc explicit de `forecast`; unitatea e m³/s ( debit ), nu cm. `quality` spune pe ce dovadă s-a deschis și până la ce orizont. N89 adaugă o a doua poartă: când comparația cu măsurătorile din ultimele 30–60 de zile arată că modelul greșește peste prag la oricare orizont (+24 / +48 / +72 h), câmpul **nu mai apare** pe stația aceea.","properties":{"model":{"type":"string","const":"glofas"},"model_version":{"type":"string","const":"4"},"dataset":{"type":"string","const":"cems-glofas-forecast"},"source":{"type":"string","const":"cems-glofas","description":"Sursa de ingest ( jobul `cems-prognoza` )."},"issued_at":{"type":"string","format":"date","example":"2026-10-28","description":"Ziua emiterii C2 ( `debit_model.emis_la` )."},"unit":{"type":"string","const":"m3/s"},"official":{"type":"boolean","const":false,"description":"Mereu `false`: modelul nu e o prognoză oficială."},"label":{"type":"string","example":"model, not an official forecast","description":"Eticheta pentru consumatori, în engleză; pagina o traduce."},"quality":{"type":"object","description":"Dovada de calitate care a deschis câmpul: N46 ( prognoza vs debit măsurat, preferat ) ori N43 ( reanaliza vs debit măsurat ).","properties":{"check":{"type":"string","enum":["N46","N43"],"nullable":true,"description":"Temeiul verificării; `null` nu se întâmplă pe un răspuns publicat ( câmpul lipsește atunci )."},"horizon_days":{"type":"integer","minimum":1,"maximum":5,"description":"Până la ce orizont e dovedită prognoza; `horizons` nu trece de el."},"samples":{"type":"integer","minimum":0,"description":"Perechile de la orizontul dovedit ( N46 ) ori din fereastra N43."},"bias_percent":{"type":"number","nullable":true,"description":"Biasul relativ, % ( pozitiv = modelul peste măsurătoare )."},"correlation":{"type":"number","nullable":true,"description":"Corelația Pearson."},"nse":{"type":"number","nullable":true,"description":"NSE, doar când temeiul e N43."},"kge":{"type":"number","nullable":true,"description":"KGE, doar când temeiul e N43."}},"required":["check","horizon_days","samples","bias_percent","correlation","nse","kge"]},"horizons":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaModelOrizont"}}},"required":["model","model_version","dataset","source","issued_at","unit","official","label","quality","horizons"]},"PrognozaModelOrizont":{"type":"object","description":"O zi a prognozei modelului: debitul de control ( `discharge_m3s` ) și, unde C2 le-a scris, percentilele / extremele ansamblului.","properties":{"day":{"type":"integer","minimum":1,"maximum":5,"description":"Orizontul față de emitere ( +1…+5 )."},"date":{"type":"string","format":"date","description":"Ziua țintă ( `debit_model.zi` )."},"discharge_m3s":{"type":"number","description":"Debitul de control al modelului, m³/s."},"p25_m3s":{"type":"number","nullable":true},"p75_m3s":{"type":"number","nullable":true},"min_m3s":{"type":"number","nullable":true},"max_m3s":{"type":"number","nullable":true}},"required":["day","date","discharge_m3s","p25_m3s","p75_m3s","min_m3s","max_m3s"]},"Statie":{"type":"object","properties":{"slug":{"type":"string","example":"budapest"},"name":{"type":"string","example":"Budapest"},"country":{"type":"string","example":"HU"},"river":{"type":"string","example":"dunarea","description":"Râul normalizat; Dunărea e `dunarea`, afluenții slug-ul lor."},"river_slug":{"type":"string","description":"N102c: identitatea râului ( adresa ) când codul `river` acoperă mai multe râuri omonime; cheia **lipsește** la stațiile obișnuite."},"river_name":{"type":"string","description":"N102c: numele râului cu calificativ ( „Bistrica (Koroška)” ), numai la omonime."},"water_body":{"type":"string","example":"Duna"},"rkm":{"type":"number","nullable":true},"ldc_cm":{"type":"integer","nullable":true,"description":"Cota de apă mică ( cm )."},"hdc_cm":{"type":"integer","nullable":true,"description":"Cota de apă mare ( cm )."},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"zero_m":{"type":"number","description":"N76b: cota zero a stației ( m ), pe reperul din `zero_datum`; cheia **lipsește** când sursa nu o publică."},"zero_datum":{"type":"string","enum":["MN","A","B","N"],"description":"N76b: reperul zero-ului — Marea Neagră ( Sulina ), Adriatica ( Trieste ), Baltica ( Kronstadt ), Normalnull ( DHHN )."},"basin_area_km2":{"type":"number","description":"N76b: suprafața oficială a bazinului din amonte de stație ( km² ); cheia **lipsește** când sursa nu o publică."},"basin_area_source":{"type":"string","description":"N76b: sursa și documentul suprafeței ( `sursaSuprafataBazin` ); lipsește când valoarea nu are origine scrisă."},"water_temperature_c":{"type":"object","nullable":true,"properties":{"value":{"type":"number"},"observed_at":{"type":"string","format":"date-time"},"source":{"type":"string"}}},"discharge_m3s":{"type":"object","nullable":true,"properties":{"value":{"type":"number"},"observed_at":{"type":"string","format":"date-time"},"source":{"type":"string"}}},"air_temperature_c":{"type":"object","nullable":true,"properties":{"value":{"type":"number"},"observed_at":{"type":"string","format":"date-time"},"source":{"type":"string"}}},"forecast":{"type":"object","nullable":true,"description":"G2: doar când stația are prognoză — ultima emisiune din ultimele 48 h, dintr-o singură sursă ( AFDJ, OVF / hydroinfo, NÖ, OÖ… ), în listă și pe fișă. `horizon_hours` spune cât de departe merge emisiunea ( `orizontOre` ), fiecare orizont are banda min–max publicată de sursă, iar zilele 4–5 ( +96 / +120 h ) au `orientativ: true` ( nu declanșează alerte ).","properties":{"source":{"type":"string","nullable":true,"example":"afdj"},"issued_at":{"type":"string","format":"date-time","nullable":true},"horizon_hours":{"type":"integer","enum":[24,48,72,96,120],"description":"Ultimul orizont publicat, în ore: AFDJ +120, NÖ +48, OÖ +72…"},"horizons":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaOrizont"}}},"required":["source","issued_at","horizon_hours","horizons"]},"model_forecast":{"$ref":"#/components/schemas/PrognozaModel","nullable":true,"description":"N77: prognoza **modelului** GloFAS ( `cems-glofas-forecast` ), într-un câmp separat de `forecast`. Apare doar când stația **nu** are prognoză oficială în ultimele 48 h și când legătura C1 stație → celulă a trecut verificarea de calitate N43 / N46; altfel câmpul lipsește. `official: false` și `label` spun explicit că nu e o prognoză oficială. Unitatea e m³/s ( debit ), nu cm ( nivel )."},"freshness":{"type":"object","nullable":true,"description":"Q88: prospețimea sursei de referință — cât de des publică sursa (`interval_minutes` = N) și cât de veche e ultima citire (`age_minutes` = M); `delayed` când M trece de 2 × N. Doar pe fișa stației ( `/stations/{slug}` ), ca `_attribution`.","properties":{"source":{"type":"string","example":"afdj","description":"Sursa de referință a stației ( `readings.source` )."},"source_name":{"type":"string","example":"AFDJ (RO)","description":"Numele de produs din `surse-crawl.nume`."},"interval_minutes":{"type":"integer","example":240,"description":"N: intervalul sursei, în minute ( `sla_ore` × 60 )."},"last_reading":{"type":"string","format":"date-time","nullable":true,"description":"Momentul ultimei citiri a referinței, ISO UTC."},"age_minutes":{"type":"integer","nullable":true,"example":37,"description":"M: vârsta ultimei citiri, în minute întregi."},"delayed":{"type":"boolean","description":"`true` când M > 2 × N ( starea „întârziată” )."},"rows_24h":{"type":"integer","nullable":true,"description":"Rândurile scrise azi de sursă, din jurnalul Q62 ( `cifre24h` )."}},"required":["source","source_name","interval_minutes","last_reading","age_minutes","delayed","rows_24h"]},"reading_state":{"type":"object","description":"G3: starea citirii stației, pe fiecare rând — în listă și pe fișă. `fresh` = în termen; `stale` = mai veche decât pragul „citirii vechi” din „Setări DanubeAlert” ( implicit 48 h ); `missing` = nicio citire în sursa de referință. `age_hours` e vârsta în ore întregi, `threshold_hours` pragul aplicat. Când tabela `readings` nu poate fi citită, câmpul lipsește ( nu se raportează „fără date” pentru o eroare ).","properties":{"status":{"type":"string","enum":["fresh","stale","missing"],"description":"Starea citirii."},"last_reading":{"type":"string","format":"date-time","nullable":true,"description":"Momentul ultimei citiri din sursa de referință, ISO UTC; `null` fără citire."},"age_hours":{"type":"integer","nullable":true,"example":1392,"description":"Vârsta ultimei citiri, în ore întregi; `null` fără citire."},"threshold_hours":{"type":"integer","example":48,"description":"Pragul „citirii vechi” aplicat, în ore ( din setări )."}},"required":["status","last_reading","age_hours","threshold_hours"]},"quality":{"type":"object","description":"H4: calitatea datelor stației, într-un singur loc — în listă și pe fișă. `source` / `source_name` = sursa de referință; `last_reading`, `status`, `age_hours` și `threshold_hours` sunt exact câmpurile G3 din `reading_state` ( `fresh` = în termen, `stale` = mai veche decât pragul „citirii vechi” din „Setări DanubeAlert”, `missing` = nicio citire ). `datum` spune dacă cota e pe cota zero a stației naționale ( `national` ), pe alt zero — DanubePortal / o sursă regională sau secundară ( `other` ), pe cota absolută a sursei, fără o cotă zero locală ( `absolute`, BAFU ), ori nu se poate stabili ( `unknown` ). Când lista nu poate citi `readings`, câmpul lipsește ( ca `reading_state` ).","properties":{"source":{"type":"string","nullable":true,"example":"afdj","description":"Identificatorul sursei de referință ( `readings.source` ); `null` când nu se poate stabili."},"source_name":{"type":"string","nullable":true,"example":"AFDJ","description":"Numele public scurt al sursei; `null` fără sursă."},"last_reading":{"type":"string","format":"date-time","nullable":true,"description":"Momentul ultimei citiri din sursa de referință, ISO UTC; `null` fără citire."},"status":{"type":"string","enum":["fresh","stale","missing"],"description":"G3: starea citirii — proaspătă, „citire veche” ( peste prag ) sau fără date."},"age_hours":{"type":"integer","nullable":true,"example":2,"description":"Vârsta ultimei citiri, în ore întregi; `null` fără citire."},"threshold_hours":{"type":"integer","example":48,"description":"Pragul „citirii vechi” aplicat, în ore ( din setări )."},"datum":{"type":"string","enum":["national","other","absolute","unknown"],"description":"`national` = pe cota zero a stației naționale ( sursa de referință a țării ori un zero documentat în tabela de datum ); `other` = pe alt zero ( DanubePortal / istoric `cote-legacy`, sursă regională sau secundară ); `absolute` = cota absolută a sursei, nu o înălțime față de cota zero a stației ( BAFU ); `unknown` = fără citire sau fără sursă."}},"required":["source","source_name","last_reading","status","age_hours","threshold_hours","datum"]},"coverage":{"type":"object","nullable":true,"description":"Q94: acoperirea seriei pe ultimele 365 de zile (ziua de ieri inclusiv), pe sursă — zilele cu citiri, lacunele consecutive și motivul lor când e cunoscut (sursa oprită / căzută / în eroare / întârziată, ori stația retrasă când sursa e încă vie). Din `readings_daily` + `surse-crawl`, doar pe fișa stației.","properties":{"from":{"type":"string","example":"2025-10-25","description":"Prima zi a ferestrei (YYYY-MM-DD, ziua locală a țării)."},"to":{"type":"string","example":"2026-10-24","description":"Ultima zi încheiată a ferestrei (ieri, în fusul țării)."},"days":{"type":"integer","example":365,"description":"Lungimea ferestrei, în zile."},"covered_days":{"type":"integer","example":361,"description":"Zilele din fereastră cu cel puțin o citire, din orice sursă."},"sources":{"type":"array","description":"Sursele raportate: referința stației întâi, apoi sursele relevante țării și cele care au citiri.","items":{"type":"object","properties":{"source":{"type":"string","example":"afdj","description":"Identificatorul sursei (`readings.source`)."},"source_name":{"type":"string","example":"AFDJ (RO)","description":"Numele de produs din `surse-crawl.nume` sau identificatorul."},"reference":{"type":"boolean","description":"`true` pentru sursa de referință a stației."},"days":{"type":"integer","example":351,"description":"Zilele cu citiri în fereastră."},"derived_days":{"type":"integer","example":12,"description":"Din `days`, zilele acoperite doar de o serie derivată a aceleiași stații, adusă pe zero-ul sursei: rezerva (alt martor ori DanubePortal) sau malul opus."},"missing_days":{"type":"integer","example":14,"description":"Zilele fără citiri în fereastră: lungimea ferestrei minus `days`."},"percent":{"type":"number","example":96.2,"description":"Procentul acoperit din fereastră (o zecimală)."},"first_day":{"type":"string","format":"date","nullable":true,"description":"Prima zi cu citiri; `null` fără nicio citire."},"last_day":{"type":"string","format":"date","nullable":true,"description":"Ultima zi cu citiri; `null` fără nicio citire."},"gaps":{"type":"array","description":"Lacunele consecutive din fereastră, cronologic (inclusiv cea de la început și cea de la coadă).","items":{"type":"object","properties":{"from":{"type":"string","format":"date","description":"Prima zi lipsă."},"to":{"type":"string","format":"date","description":"Ultima zi lipsă (inclusiv)."},"days":{"type":"integer","description":"Câte zile are lacuna."},"reason":{"type":"string","nullable":true,"enum":["series_starts_later","source_disabled","source_down","source_error","source_late","station_retired"],"description":"Motivul când e cunoscut: serie începută mai târziu, sursă oprită / căzută / în eroare / întârziată, stație retrasă; `null` pentru o lacună internă sau o sursă fără telemetrie."}},"required":["from","to","days","reason"]}}},"required":["source","source_name","reference","days","derived_days","missing_days","percent","first_day","last_day","gaps"]}}},"required":["from","to","days","covered_days","sources"]},"anomaly":{"$ref":"#/components/schemas/Anomalie","description":"D2: abaterea nivelului ultimei citiri față de climatologia zilei ei ( D1 ). Doar pe fișa stației ( `/stations/{slug}` ); în listă lipsește. Lipsește și când nu există destul istoric ( sub 10 ani ) sau când tabela materializată nu e disponibilă."},"proposed_thresholds":{"$ref":"#/components/schemas/PropunerePraguri","description":"F1: cotele propuse ( p10 „apă mică” / p90 „apă mare” ) pentru stațiile fără LDC/HDC, din seria de referință. Doar pe fișa stației ( `/stations/{slug}` ); lipsește în listă, pe stațiile cu praguri și sub 10 ani de referință."},"_attribution":{"$ref":"#/components/schemas/Atribuire","description":"Doar pe fișa stației ( `/stations/{slug}` ); în listă e o singură dată, pe răspuns ( QA live #28 )."}}},"PaginaStatii":{"type":"object","description":"Lista paginată ( cursor keyset pe id: `next_cursor` → `?next_cursor=` ). `total` = stațiile care se potrivesc filtrelor, oricare ar fi cursorul. `_attribution` e o singură dată, pe răspuns ( QA live #28 ): elementele listei nu-l mai repetă — fișa unei stații ( `/stations/{slug}` ) îl păstrează.","properties":{"total":{"type":"integer","description":"Câte stații se potrivesc filtrelor ( `country`, `river`, `q` ), pe toate paginile."},"data":{"type":"array","items":{"$ref":"#/components/schemas/Statie"},"description":"Stațiile paginii, fără `_attribution` ( e pe răspuns )."},"next_cursor":{"type":"string","nullable":true},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["total","data","next_cursor","_attribution"]},"Masuratori":{"type":"object","description":"Nivelul apei în cm; `timezone` local unde e relevant.","properties":{"station":{"type":"string"},"interval":{"type":"string","enum":["raw","hourly","daily"]},"source":{"type":"string","description":"Sursa seriei din `data`: referința stației sau cea cerută cu `source=`."},"data":{"type":"array","items":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time"},"level_cm":{"type":"number"}}}},"legacy":{"type":"object","nullable":true,"description":"Doar cu `include_legacy=true`: stratul DanubePortal / legacy în aceeași fereastră. Decizia de datum e pe toate zilele comune cu referința: `same` ( același zero, ±3 cm ), `offset` ( decalaj constant, aplicat ), `unknown` ( sub 5 zile comune ), `variable` ( nu se aliniază ).","properties":{"source":{"type":"string","const":"danubeportal"},"datum":{"type":"object","properties":{"status":{"type":"string","enum":["same","offset","unknown","variable"]},"offset_cm":{"type":"integer","nullable":true},"common_days":{"type":"integer"}}},"data":{"type":"array","items":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time"},"level_cm":{"type":"number"},"level_cm_aligned":{"type":"number","nullable":true}}}}}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}}},"Debit":{"type":"object","description":"Seria de debit ( Q, m³/s ) din `masuratori`; `source` e sursa seriei din `data` ( una singură ).","properties":{"station":{"type":"string"},"interval":{"type":"string","enum":["raw","hourly","daily"]},"source":{"type":"string","nullable":true,"description":"Sursa seriei: cea mai nouă măsurătoare de debit sau cea cerută cu `source=`."},"unit":{"type":"string","const":"m³/s"},"data":{"type":"array","items":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time"},"discharge_m3s":{"type":"number"}}}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["station","interval","source","unit","data","_attribution"]},"Rauri":{"type":"object","description":"Râurile din bazin, cu numărul de stații; `dunarea` e implicitul celorlalte rute.","properties":{"data":{"type":"array","items":{"type":"object","properties":{"river":{"type":"string"},"stations":{"type":"integer"}}}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}}},"PaginaV2":{"type":"object","description":"Pagina de listă v2: rândurile ( proiectate după `fields` ) și cursorul următoarei pagini (`null` la capăt ).","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"next_cursor":{"type":"string","nullable":true,"description":"Cursorul opac al paginii următoare; `null` când lista s-a terminat."},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["data","next_cursor"]},"FeatureCollectionV2":{"type":"object","description":"Reprezentarea GeoJSON a listei: un `Feature` per rând, cu `Point` unde resursa are coordonate.","properties":{"type":{"type":"string","const":"FeatureCollection"},"features":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"Feature"},"geometry":{"type":"object","nullable":true,"description":"`Point` pentru resursele cu coordonate, `null` altfel."},"properties":{"type":"object","additionalProperties":true}}}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["type","features"]},"Calitate":{"type":"object","description":"Agregat pe stație al calității datelor; doar stațiile cu citiri sau suspecte.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CalitateStatie"}},"generated_at":{"type":"string","format":"date-time"},"_attribution":{"$ref":"#/components/schemas/Atribuire"}}},"CalitateStatie":{"type":"object","description":"O stație: ultima citire, numărul de suspecte și starea sursei ultimei citiri.","properties":{"station_id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"country":{"type":"string","nullable":true},"source":{"type":"string","nullable":true},"last_reading_at":{"type":"string","format":"date-time","nullable":true},"suspect_count":{"type":"integer"},"last_suspect_at":{"type":"string","format":"date-time","nullable":true},"source_state":{"type":"string","enum":["ok","eroare","stale","cazuta"],"nullable":true,"description":"`stale` = fără citiri în termen ( „invechit” ); `cazuta` = fără scrieri de peste 2 × intervalul sursei ( jobul zilnic de sănătate )."}}},"Prag":{"type":"object","description":"Un prag activ, cu sursa și data declarată de ea; `statie_slug` lipsește când stația nu e încă în registru.","properties":{"id":{"type":"integer"},"statie":{"type":"integer","nullable":true},"statie_slug":{"type":"string","nullable":true,"example":"budapest"},"nume_statie":{"type":"string","nullable":true,"description":"Numele stației în scrierea sursei."},"rau":{"type":"string","nullable":true},"rkm":{"type":"number","nullable":true},"sursa":{"type":"string","nullable":true,"example":"pegelonline"},"tip":{"type":"string","enum":["ldc","hdc","hdc100","zero","rnw","hsw","hsw2","zs1","m1","m2","m3","defence_1","defence_2"]},"nume":{"type":"string","nullable":true,"description":"Termenul național al pragului ( LDC, RNW, Redovna odbrana… )."},"valoare":{"type":"number"},"unitate":{"type":"string","enum":["cm","m","m3s"]},"data":{"type":"string","nullable":true,"description":"Data declarată de sursă ( vintage-ul valorii )."},"url":{"type":"string","nullable":true,"format":"uri"},"activ":{"type":"boolean","const":true}}},"Praguri":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Prag"}},"meta":{"type":"object","properties":{"totalDocs":{"type":"integer"},"totalPages":{"type":"integer"},"page":{"type":"integer"},"limit":{"type":"integer"},"hasNextPage":{"type":"boolean"},"hasPrevPage":{"type":"boolean"}}}}},"Comparatie":{"type":"object","description":"Până la 6 stații, fiecare cu seria ei; același `_attribution`.","properties":{"stations":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"river":{"type":"string"},"ldc_cm":{"type":"integer","nullable":true},"hdc_cm":{"type":"integer","nullable":true},"observations":{"type":"array","items":{"type":"object","properties":{"observed_at":{"type":"string","format":"date-time"},"level_cm":{"type":"number"}}}}}}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}}},"Navigatie":{"type":"object","description":"Puncte critice și restricții de navigație active; câmpurile lipsă sunt `null`. Restricțiile vin doar din sursele păstrate ( AFDJ ).","properties":{"puncte_critice":{"type":"array","items":{"$ref":"#/components/schemas/PunctCritic"}},"restrictii":{"type":"array","items":{"$ref":"#/components/schemas/RestrictieNavigatie"}}}},"PunctCritic":{"type":"object","description":"Punct critic activ. `cota_sondaj`, `adancime_sondaj` și `adancime_minima` sunt în `unitate` ( cm implicit ); `adancime_estimata` e în cm.","properties":{"id":{"type":"integer"},"nume":{"type":"string","nullable":true},"rau":{"type":"string","example":"dunarea"},"rkm":{"type":"number","nullable":true},"latitudine":{"type":"number","nullable":true},"longitudine":{"type":"number","nullable":true},"tip":{"type":"string","enum":["prag","dragaj","pod","baraj","confluenta","altele"]},"descriere":{"type":"string","nullable":true},"sursa":{"type":"string","nullable":true,"example":"doris"},"url":{"type":"string","nullable":true,"format":"uri"},"data":{"type":"string","nullable":true,"format":"date-time"},"cod_sursa":{"type":"string","nullable":true,"description":"Identificatorul stabil al rândului în sursă."},"mira":{"type":"integer","nullable":true,"description":"Id-ul stației de referință."},"mira_nume":{"type":"string","nullable":true},"unitate":{"type":"string","enum":["cm","m"],"description":"Unitatea cotei și a adâncimilor sondajului."},"cota_sondaj":{"type":"number","nullable":true,"description":"Cota apei la stația de referință în ziua sondajului, în `unitate`."},"adancime_sondaj":{"type":"number","nullable":true,"description":"Cea mai mică adâncime din sondaj, în `unitate` ( la AFDJ, minimul EV/IV/C/IR/ER )."},"adancime_minima":{"type":"number","nullable":true,"description":"Cea mai mică adâncime de navigație publicată de avizul sursei, în `unitate` ( AFDJ: minimul sondajului; Plovput: HMIN; viadonau: adâncimea șenalului marcat )."},"adancime_estimata":{"type":"number","nullable":true,"description":"Adâncimea de azi, în cm: `adancime_minima + ( cota_actuală − cota_sondaj )`, ambele cote aduse la cm. `null` fără cota în fereastra de vechime."},"sursa_cota":{"type":"string","nullable":true,"example":"afdj","description":"Sursa citirii curente ( `readings.source` ), nu sursa punctului."},"data_cota":{"type":"string","nullable":true,"format":"date-time","description":"Momentul citirii curente."},"data_sondaj":{"type":"string","nullable":true,"format":"date-time"},"data_aviz":{"type":"string","nullable":true,"format":"date-time","description":"Ziua avizului/buletinului care publică `adancime_minima` ( AFDJ: data măsurătorii; Plovput: data buletinului; viadonau: data interogării )."},"activ":{"type":"boolean"}}},"RestrictieNavigatie":{"type":"object","description":"Restricție de navigație activă, numai din sursele păstrate ( AFDJ ); DoRIS nu mai publică restricții.","properties":{"id":{"type":"integer"},"titlu":{"type":"string","nullable":true},"rau":{"type":"string","example":"dunarea"},"sector":{"type":"string","nullable":true},"rkm_start":{"type":"number","nullable":true},"rkm_end":{"type":"number","nullable":true},"tip":{"type":"string","enum":["adancime","latime","viteza","lucrari","inchidere","altele"]},"descriere":{"type":"string","nullable":true},"sursa":{"type":"string","nullable":true,"example":"afdj","description":"Sursa rândului; restricțiile se publică doar din sursele păstrate ( AFDJ )."},"url":{"type":"string","nullable":true,"format":"uri"},"data_start":{"type":"string","nullable":true,"format":"date-time"},"data_end":{"type":"string","nullable":true,"format":"date-time"},"cod_sursa":{"type":"string","nullable":true,"description":"Identificatorul stabil al rândului în sursă."},"activ":{"type":"boolean"}}},"SursaCalitate":{"type":"object","description":"O sursă de crawl: ultima rulare și calitatea ei în timp (Q32), plus scrierile din ultimele 24 h (Q54).","properties":{"sursa":{"type":"string","nullable":true,"example":"afdj"},"nume":{"type":"string","nullable":true,"example":"AFDJ (RO)"},"stare":{"type":"string","nullable":true,"enum":["ok","eroare","stale","cazuta",null],"description":"Starea sursei: `ok`; `eroare` = ultima rulare a picat **și** datele de dinainte au ieșit din SLA (o cădere de rețea cât timp datele sunt încă în termen nu ridică starea, ci lasă doar `ultima_eroare`); `stale` = fără citiri în termenul SLA (jobul orar); `cazuta` = nu a mai scris nimic de peste 2 × intervalul ei (jobul zilnic de sănătate)."},"ultima_succes":{"type":"string","nullable":true,"format":"date-time","description":"Ultima rulare terminată cu succes (poate să nu fi scris nimic)."},"ultima_scriere":{"type":"string","nullable":true,"format":"date-time","description":"Ultima rulare care a scris ceva (citiri, buletine sau praguri); `null` = încă necunoscut."},"citite_24h":{"type":"integer","nullable":true,"description":"Rânduri citite din sursă în ultimele 24 h, cumulat pe rulări (Q54)."},"scrise_24h":{"type":"integer","nullable":true,"description":"Citiri scrise de sursă în ultimele 24 h (Q54)."},"ultimele_randuri":{"type":"integer","nullable":true},"sla_ore":{"type":"number","description":"SLA-ul sursei, în ore (câmpul `slaOre` din panou sau implicitul sursei)."},"uptime_7d":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Fracția din ultimele 7 zile în care sursa a fost în termen (0–1). `null` = fără date."},"uptime_30d":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Aceeași fracție pe 30 de zile."},"intarziere_medie_ore":{"type":"number","nullable":true,"description":"Vârsta medie a celei mai proaspete citiri, în ore, pe 7 zile (prospețimea datelor)."},"ultima_eroare":{"type":"string","nullable":true,"format":"date-time","description":"Momentul ultimei rulări eșuate; rămâne și după revenire."},"ultima_eroare_mesaj":{"type":"string","nullable":true,"description":"Mesajul ultimei erori (fără date personale)."}},"required":["sursa","sla_ore","uptime_7d","uptime_30d","intarziere_medie_ore","ultima_eroare","ultima_eroare_mesaj"]},"Atribuire":{"type":"object","description":"Blocul obligatoriu de citare ( §6 ); exporturile open-data adaugă și licența. `source` e mereu în engleză, indiferent de `Accept-Language` sau `?lang=`: corpul rămâne același între cereri ( cache, `ETag` ). Fraza surselor pe limba cititorului e pe `/{lang}/about`, ținta lui `url`; instituțiile sunt în `/v1/meta/sources`.","properties":{"source":{"type":"string","description":"Sursa datelor, în engleză ( de exemplu „National hydrological services of the Danube basin (see /v1/meta/sources)” )."},"url":{"type":"string","format":"uri","description":"Pagina „About”, cu sursele enumerate."},"license":{"type":"object","description":"Licența datelor exportate: CC BY 4.0.","properties":{"id":{"type":"string","const":"CC-BY-4.0"},"name":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["id","name","url"]},"data_updated_at":{"type":"string","format":"date-time"},"weather":{"type":"object","description":"Doar pe `/basin-precipitation` ( D7 ): sursa meteo de creditat, cum cere licența ei — linkul și licența lângă cifre. Restul rutelor nu îl au.","properties":{"source":{"type":"string","const":"Open-Meteo"},"url":{"type":"string","format":"uri"},"license":{"type":"string","const":"CC BY 4.0"},"license_url":{"type":"string","format":"uri"}},"required":["source","url","license","license_url"]}}},"Climatologie":{"type":"object","description":"Seria de referință a stației, pe zile calendaristice: câți ani, media, mediana, percentilele 10 / 25 / 75 / 90, minimul, maximul și abaterea standard. Doar sursa de referință efectivă a stației.","properties":{"station":{"type":"string","example":"budapest"},"name":{"type":"string","example":"Budapest"},"country":{"type":"string","nullable":true,"example":"HU"},"river":{"type":"string","example":"dunarea"},"source":{"type":"string","example":"vizugy","description":"Sursa de referință aleasă pentru serie ( `statii.sursa_referinta_efectiva` sau referința țării )."},"timezone":{"type":"string","example":"Europe/Budapest"},"day":{"type":"string","nullable":true,"example":"10-24","description":"Ziua cerută `MM-DD`; `null` când s-a cerut seria întreagă."},"min_years":{"type":"integer","example":10,"description":"Sub acest număr de ani, abaterea de azi nu se afirmă ( rândul rămâne informativ )."},"days":{"type":"array","items":{"$ref":"#/components/schemas/ZiClimatologie"}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["station","name","country","river","source","timezone","day","min_years","days","_attribution"]},"ZiClimatologie":{"type":"object","description":"O zi calendaristică din climatologie, în cm: media, mediana și percentilele seriei de referință.","properties":{"day":{"type":"string","example":"10-24"},"years":{"type":"integer","example":32,"description":"Câți ani au contribuit la ziua asta."},"mean_level_cm":{"type":"integer","example":231},"median_level_cm":{"type":"integer","example":230},"p10_cm":{"type":"integer","example":180},"p25_cm":{"type":"integer","example":210},"p75_cm":{"type":"integer","example":250},"p90_cm":{"type":"integer","example":280},"min_level_cm":{"type":"integer","example":120},"max_level_cm":{"type":"integer","example":340},"std_dev_cm":{"type":"number","nullable":true,"example":40.5,"description":"Abaterea standard a eșantionului; `null` sub două valori."}},"required":["day","years","mean_level_cm","median_level_cm","p10_cm","p25_cm","p75_cm","p90_cm","min_level_cm","max_level_cm","std_dev_cm"]},"EvenimenteStatie":{"type":"object","description":"Evenimentele istorice documentate ale stației, sortate după an descrescător; `total` numără rândurile înainte de plafonul `limit`.","properties":{"station":{"type":"string","example":"budapest"},"events":{"type":"array","items":{"$ref":"#/components/schemas/EvenimentIstoric"}},"total":{"type":"integer","example":2,"description":"Câte evenimente se potrivesc filtrului, înainte de `limit`."},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["station","events","total","_attribution"]},"EvenimentIstoric":{"type":"object","description":"Un eveniment istoric documentat la stație: viitura ( vârful maxim ) sau seceta ( minimul ), cu sursa publică verificabilă.","properties":{"id":{"type":"integer","example":22},"tip":{"type":"string","enum":["viitura","seceta"]},"an":{"type":"integer","example":2013},"data":{"type":"string","format":"date","nullable":true,"example":"2013-06-09","description":"Ziua exactă a vârfului, `YYYY-MM-DD`; `null` când sursa dă doar anul."},"varf":{"type":"number","example":891,"description":"Cota maximă la viitură, minima la secetă, în `unitate`."},"unitate":{"type":"string","enum":["cm","m3s"],"description":"`cm` = centimetri față de cota zero a stației; `m3s` = metri cubi pe secundă."},"sursa":{"type":"string","example":"ovf","description":"Codul instituției sursă ( ovf, shmu, inhga, icpdr… )."},"sursa_nume":{"type":"string","example":"Országos Vízügyi Főigazgatóság (OVF)"},"url":{"type":"string","format":"uri","nullable":true,"example":"https://www.vizugy.hu/","description":"Adresa publică unde se verifică valoarea."}},"required":["id","tip","an","data","varf","unitate","sursa","sursa_nume","url"]},"Anomalie":{"type":"object","description":"D2: abaterea unei stații față de normalul zilei ( mediana climatologiei D1 ). `anomaly_cm` = nivelul minus normalul; `z_score` standardizează față de media și deviația seriei ( `null` fără deviație utilă ); `category` folosește percentilele: very_low sub p10, low sub p25, high peste p75, very_high peste p90.","properties":{"station":{"type":"string","example":"budapest"},"name":{"type":"string","example":"Budapest"},"country":{"type":"string","nullable":true,"example":"HU"},"date":{"type":"string","format":"date","example":"2026-10-23","description":"Ziua citirii ( `YYYY-MM-DD`, ziua locală a țării )."},"day":{"type":"string","example":"10-23","description":"Ziua calendaristică a citirii ( `MM-DD` )."},"level_cm":{"type":"integer","example":240},"normal_level_cm":{"type":"integer","example":155,"description":"Mediana climatologiei zilei, în cm."},"mean_level_cm":{"type":"integer","example":155,"description":"Media climatologiei zilei, în cm."},"anomaly_cm":{"type":"integer","example":85,"description":"Nivelul minus normalul; pozitiv = peste normal."},"z_score":{"type":"number","nullable":true,"example":2.4,"description":"( nivel − media ) / deviația standard a seriei; `null` fără deviație utilă."},"category":{"type":"string","enum":["very_low","low","normal","high","very_high"]},"years":{"type":"integer","example":32,"description":"Anii de referință ai zilei ( minimum 10, ca anomalia să fie afirmată )."}},"required":["station","name","country","date","day","level_cm","normal_level_cm","mean_level_cm","anomaly_cm","z_score","category","years"]},"PropunerePraguri":{"type":"object","description":"F1: pragurile propuse pentru o stație **fără LDC/HDC**, din seria de referință a stației ( prima citire a zilei locale, aceeași convenție ca D1 ): „apă mică” = p10, „apă mare” = p90. Sunt propuneri pentru formularul de alerte ( tipul de prag `percentila` ), nu praguri oficiale: nu se scriu în `ldc_cm` / `hdc_cm` și nu schimbă LDC/HDC sau nivelul custom. Lipsește pe stațiile cu praguri și sub 10 ani de referință.","properties":{"low_water_cm":{"type":"integer","example":-128,"description":"Cota „apă mică” ( p10 ), în cm."},"high_water_cm":{"type":"integer","example":444,"description":"Cota „apă mare” ( p90 ), în cm."},"low_percentile":{"type":"integer","enum":[10],"description":"Percentila cotei mici ( 10 )."},"high_percentile":{"type":"integer","enum":[90],"description":"Percentila cotei mari ( 90 )."},"years":{"type":"integer","example":12,"description":"Anii distincți din seria de referință ( minimum 10 )."},"source":{"type":"string","example":"vizugy","description":"Sursa de referință a stației ( `readings.source` )."}},"required":["low_water_cm","high_water_cm","low_percentile","high_percentile","years","source"]},"UndaSchimbare":{"type":"object","description":"F4: unda Q74 care pleacă din stația schimbării spre vecinul din aval — mediana întârzierii și intercuartilul benzii nivelului de acum.","properties":{"station":{"type":"string","example":"lom","description":"Slugul stației din aval."},"name":{"type":"string","example":"Lom"},"km":{"type":"number","example":90.3,"description":"Distanța dintre cele două stații, din perechea Q74."},"hours":{"type":"number","example":14.4,"description":"Mediana întârzierii undei, în ore."},"hours_q1":{"type":"number","example":9.4,"description":"Intercuartilul Q1 al întârzierii, în ore."},"hours_q3":{"type":"number","example":19.6,"description":"Intercuartilul Q3 al întârzierii, în ore."},"episodes":{"type":"integer","example":167,"description":"Episoadele din care s-a calculat banda ( minimum 5, regula produsului )."}},"required":["station","name","km","hours","hours_q1","hours_q3","episodes"]},"Schimbare":{"type":"object","description":"F4: o schimbare semnificativă a zilei, pe stație. `kind` spune semnalul dominant: `rise` / `fall` = variația pe 24 h peste pragul de 25 cm, `wave` = o creștere din care pleacă o undă Q74, `anomaly` = abaterea D2 fără o mișcare a zilei. Câmpurile celorlalte semnale rămân în rând ( `anomaly_cm`, `wave` ), ca aceeași stație să nu apară de două ori.","properties":{"kind":{"type":"string","enum":["rise","fall","wave","anomaly"],"description":"Semnalul dominant al rândului."},"station":{"type":"string","example":"novo-selo"},"name":{"type":"string","example":"Novo Selo"},"country":{"type":"string","nullable":true,"example":"BG"},"river":{"type":"string","example":"dunarea","description":"Cheia râului pentru URL-uri și filtre ( `dunarea`, `tisa`, … )."},"rkm":{"type":"number","nullable":true,"example":833.6},"date":{"type":"string","format":"date","example":"2014-05-17","description":"Ziua citirii ( ziua locală a țării )."},"level_cm":{"type":"integer","example":778},"change_24h_cm":{"type":"integer","nullable":true,"example":113,"description":"Variația pe 24 h; `null` fără ziua precedentă consecutivă."},"normal_level_cm":{"type":"integer","nullable":true,"example":339,"description":"D2: mediana climatologiei zilei; `null` fără destul istoric ori fără D1."},"anomaly_cm":{"type":"integer","nullable":true,"example":439,"description":"D2: nivelul minus normalul zilei; pozitiv = peste normal."},"z_score":{"type":"number","nullable":true,"example":1.8,"description":"D2: abaterea standardizată față de media seriei; `null` fără deviație utilă."},"category":{"type":"string","nullable":true,"enum":["very_low","low","normal","high","very_high"],"description":"D2: categoria abaterii față de percentilele zilei; `null` fără anomalie."},"wave":{"anyOf":[{"$ref":"#/components/schemas/UndaSchimbare"},{"type":"null"}],"description":"Q74: unda care pleacă din stație, doar la o creștere semnificativă; `null` altfel."},"significance":{"type":"integer","example":113,"description":"Cel mai mare centimetraj al semnalului dominant ( ordinea listei )."}},"required":["kind","station","name","country","river","rkm","date","level_cm","change_24h_cm","normal_level_cm","anomaly_cm","z_score","category","wave","significance"]},"SchimbariTara":{"type":"object","description":"F4: schimbările semnificative ale unei țări, cu totalul dinainte de plafon.","properties":{"country":{"type":"string","nullable":true,"example":"BG","description":"Cod ISO; `null` pentru stațiile fără țară."},"total":{"type":"integer","example":5,"description":"Câte schimbări are țara, înainte de plafonul pe țară."},"changes":{"type":"array","items":{"$ref":"#/components/schemas/Schimbare"},"description":"Primele schimbări ale țării ( cel mult 3 )."}},"required":["country","total","changes"]},"SituatiaAzi":{"type":"object","description":"Sinteza zilei: totalul și câte un rând pe țară. `data_updated_at` e cea mai nouă zi de citire; `generated_at`, momentul răspunsului.","properties":{"generated_at":{"type":"string","format":"date-time"},"data_updated_at":{"type":"string","format":"date-time","nullable":true},"total":{"$ref":"#/components/schemas/SituatieTotal"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/SituatieTara"}},"anomaly_date":{"type":"string","format":"date-time","nullable":true,"description":"D2: ziua cea mai nouă a anomaliilor ( ISO UTC ); `null` fără anomalii."},"anomaly_ranking":{"type":"array","items":{"$ref":"#/components/schemas/Anomalie"},"description":"D2: cele mai mari abateri de la normalul zilei, după abaterea standardizată ( cel mult 10 )."},"changes_date":{"type":"string","format":"date-time","nullable":true,"description":"F4: ziua cea mai nouă dintre schimbările semnificative ( ISO UTC ); `null` fără schimbări."},"changes":{"type":"array","items":{"$ref":"#/components/schemas/Schimbare"},"description":"F4: primele schimbări semnificative ale zilei ( cel mult 6 ), ordonate după mărime: mișcarea pe 24 h, unda Q74 și abaterea D2."},"changes_by_country":{"type":"array","items":{"$ref":"#/components/schemas/SchimbariTara"},"description":"F4: aceleași schimbări grupate pe țară ( cel mult 3 pe țară ), țările în ordinea primei apariții în clasament."},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["generated_at","data_updated_at","total","countries","anomaly_date","anomaly_ranking","changes_date","changes","changes_by_country","_attribution"]},"SituatieTotal":{"type":"object","description":"Contoarele unei țări ( sau totalul ): doar stațiile cu citire proaspătă intră la praguri.","properties":{"stations":{"type":"integer"},"with_thresholds":{"type":"integer","description":"Stații cu citire proaspătă și LDC/HDC."},"below_ldc":{"type":"integer"},"above_hdc":{"type":"integer"},"normal":{"type":"integer"},"no_data":{"type":"integer","description":"Fără citire în ultimele 48 h."},"percent_below_ldc":{"type":"integer","nullable":true,"description":"Din stațiile cu praguri; `null` fără praguri."},"percent_above_hdc":{"type":"integer","nullable":true},"trends":{"$ref":"#/components/schemas/TendinteSituatie"},"forecasts":{"$ref":"#/components/schemas/PrognozeSituatie"},"with_climatology":{"type":"integer","description":"D2: stații cu anomalie calculată ( citire proaspătă și cel puțin 10 ani de climatologie )."},"above_normal":{"type":"integer","description":"D2: peste p75 zilei ( ridicat + foarte ridicat )."},"below_normal":{"type":"integer","description":"D2: sub p25 zilei ( jos + foarte jos )."},"within_normal":{"type":"integer","description":"D2: între p25 și p75."}},"required":["stations","with_thresholds","below_ldc","above_hdc","normal","no_data","percent_below_ldc","percent_above_hdc","trends","forecasts","with_climatology","above_normal","below_normal","within_normal"]},"TendinteSituatie":{"type":"object","description":"Semnul variației de 24 h al citirii de referință; `unknown` fără citire proaspătă sau fără ziua precedentă.","properties":{"rising":{"type":"integer"},"falling":{"type":"integer"},"stable":{"type":"integer"},"unknown":{"type":"integer"}},"required":["rising","falling","stable","unknown"]},"PrognozeSituatie":{"type":"object","description":"Prognoza ultimei emisiuni ( Q21 ): `stations` au prognoză, `above_hdc` / `below_ldc` o ating în 24–72 h, iar `rising` / `falling` / `stable` compară ultimul orizont cu nivelul de acum.","properties":{"stations":{"type":"integer"},"above_hdc":{"type":"integer"},"below_ldc":{"type":"integer"},"rising":{"type":"integer"},"falling":{"type":"integer"},"stable":{"type":"integer"},"unknown":{"type":"integer"}},"required":["stations","above_hdc","below_ldc","rising","falling","stable","unknown"]},"SituatieTara":{"description":"Un rând de țară: contoarele totale plus codul și numele țării.","allOf":[{"$ref":"#/components/schemas/SituatieTotal"},{"type":"object","properties":{"country":{"type":"string","nullable":true,"description":"Cod ISO; `null` pentru stațiile fără țară."},"name":{"type":"string"}},"required":["country","name"]}]},"RaportZi":{"type":"object","description":"Răspunsul `/report/today`: raportul zilei și atribuirea surselor. `report` este obiectul tipizat al raportului.","properties":{"generated_at":{"type":"string","format":"date-time"},"report":{"$ref":"#/components/schemas/RaportZilnic"},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["generated_at","report","_attribution"]},"RaportZilnic":{"type":"object","description":"Raportul zilei: starea pe bazin, schimbările F4, stațiile sub/peste praguri și prognoza 24–72 h din G2. Fără date, `date` este `null`, iar listele sunt goale — nu se inventează un raport.","properties":{"date":{"type":"string","format":"date","nullable":true,"description":"Ziua raportului: cea mai nouă citire ( `YYYY-MM-DD` ); `null` fără citiri."},"basin":{"$ref":"#/components/schemas/StareBazin"},"changes":{"$ref":"#/components/schemas/SchimbariRaport"},"thresholds":{"$ref":"#/components/schemas/PraguriRaport"},"forecast":{"$ref":"#/components/schemas/PrognozaRaportZi"}},"required":["date","basin","changes","thresholds","forecast"]},"StareBazin":{"type":"object","description":"Starea pe bazin: exact agregatul „Situația azi” ( totalul și câte un rând pe țară ).","properties":{"total":{"$ref":"#/components/schemas/SituatieTotal"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/SituatieTara"}}},"required":["total","countries"]},"SchimbariRaport":{"type":"object","description":"F4: „ce se schimbă azi” — aceleași trei câmpuri ca în `/summary/today`, refolosite ca atare.","properties":{"changes_date":{"type":"string","format":"date-time","nullable":true,"description":"Ziua cea mai nouă dintre schimbări ( ISO UTC ); `null` fără schimbări."},"changes":{"type":"array","items":{"$ref":"#/components/schemas/Schimbare"},"description":"Primele schimbări semnificative ale zilei ( cel mult 6 )."},"changes_by_country":{"type":"array","items":{"$ref":"#/components/schemas/SchimbariTara"},"description":"Aceleași schimbări grupate pe țară ( cel mult 3 pe țară )."}},"required":["changes_date","changes","changes_by_country"]},"PraguriRaport":{"type":"object","description":"Stațiile cu citire proaspătă ( 48 h ) sub LDC / peste HDC, cu pragul încălcat și diferența în cm.","properties":{"below_ldc":{"type":"array","items":{"$ref":"#/components/schemas/StatiePrag"},"description":"Stații sub LDC, cele mai grave primele ( diferența în modul descrescătoare )."},"above_hdc":{"type":"array","items":{"$ref":"#/components/schemas/StatiePrag"},"description":"Stații peste HDC, cele mai grave primele."}},"required":["below_ldc","above_hdc"]},"StatiePrag":{"type":"object","description":"O stație sub LDC sau peste HDC: nivelul de acum, ambele praguri, pragul încălcat și diferența.","properties":{"station":{"type":"string","description":"Slugul stației."},"name":{"type":"string"},"country":{"type":"string","nullable":true,"description":"Cod ISO; `null` pentru stațiile fără țară."},"river":{"type":"string","description":"Cheia râului pentru URL-uri ( `dunarea`, `tisa`, … )."},"rkm":{"type":"number","nullable":true},"date":{"type":"string","format":"date","description":"Ziua citirii ( ziua locală a țării )."},"level_cm":{"type":"integer"},"ldc_cm":{"type":"integer","nullable":true,"description":"LDC valid ( poate fi negativ pe Dunărea de jos ); `null` fără prag."},"hdc_cm":{"type":"integer","nullable":true},"threshold":{"type":"string","enum":["ldc","hdc"],"description":"Pragul încălcat."},"threshold_cm":{"type":"integer","description":"Valoarea pragului încălcat."},"difference_cm":{"type":"integer","description":"`level_cm - threshold_cm`: negativ sub LDC, pozitiv peste HDC."}},"required":["station","name","country","river","rkm","date","level_cm","ldc_cm","hdc_cm","threshold","threshold_cm","difference_cm"]},"PrognozaRaportZi":{"type":"object","description":"Prognoza 24–72 h din G2, doar stațiile cu o prognoză semnificativă ( atinge un prag ori mișcă cel puțin 25 cm ), plafonată pe bazin și pe țară.","properties":{"window_hours":{"type":"object","description":"Fereastra de alertă a prognozei ( G2 ): 24–72 h.","properties":{"min":{"type":"integer","example":24},"max":{"type":"integer","example":72}},"required":["min","max"]},"total":{"type":"integer","description":"Câte prognoze sunt semnificative, înainte de plafonul listei globale."},"stations":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaRaport"},"description":"Primele 12 prognoze semnificative, în ordinea semnificației."},"by_country":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaTara"},"description":"Aceleași prognoze grupate pe țară ( cel mult 3 pe țară )."}},"required":["window_hours","total","stations","by_country"]},"PrognozaTara":{"type":"object","description":"Prognozele semnificative ale unei țări, cu totalul dinainte de plafon.","properties":{"country":{"type":"string","nullable":true,"description":"Cod ISO; `null` pentru stațiile fără țară."},"total":{"type":"integer"},"stations":{"type":"array","items":{"$ref":"#/components/schemas/PrognozaRaport"}}},"required":["country","total","stations"]},"PrognozaRaport":{"type":"object","description":"Prognoza 24–72 h a unei stații: sursa și orizontul emisiunii, pragurile, atingerea lor și orizonturile din fereastră.","properties":{"station":{"type":"string","description":"Slugul stației."},"name":{"type":"string"},"country":{"type":"string","nullable":true},"river":{"type":"string"},"rkm":{"type":"number","nullable":true},"source":{"type":"string","nullable":true,"description":"Sursa emitentă ( `afdj`, `hydroinfo`, `noe`, `ooe`… )."},"issued_at":{"type":"string","format":"date-time","nullable":true},"source_horizon_hours":{"type":"integer","description":"Cât de departe merge emisiunea sursei ( `horizon_hours` din G2 ); pot fi 96 / 120 h, deși raportul afișează doar 24–72 h."},"ldc_cm":{"type":"integer","nullable":true},"hdc_cm":{"type":"integer","nullable":true},"current_level_cm":{"type":"integer","nullable":true,"description":"Nivelul citirii proaspete; `null` fără citire proaspătă."},"change_cm":{"type":"integer","nullable":true,"description":"Ultimul orizont din fereastră minus nivelul de acum; `null` fără citire proaspătă."},"reaches_ldc":{"type":"boolean","description":"Prognoza centrală atinge LDC în 24–72 h."},"reaches_hdc":{"type":"boolean","description":"Prognoza centrală atinge HDC în 24–72 h."},"significance":{"type":"integer","description":"Cel mai mare centimetraj dintre atingerea pragului și mișcarea față de acum ( ordinea listei )."},"horizons":{"type":"array","items":{"$ref":"#/components/schemas/OrizontRaport"},"description":"Orizonturile 24 / 48 / 72 h, cu banda min–max unde sursa o dă."}},"required":["station","name","country","river","rkm","source","issued_at","source_horizon_hours","ldc_cm","hdc_cm","current_level_cm","change_cm","reaches_ldc","reaches_hdc","significance","horizons"]},"OrizontRaport":{"type":"object","description":"Un orizont de prognoză din fereastra 24–72 h ( forma G2, fără zilele 4–5 ).","properties":{"day":{"type":"integer","description":"Ziua orizontului ( 1…3 )."},"horizon_h":{"type":"integer","enum":[24,48,72]},"level_cm":{"type":"integer","description":"Nivelul central prognozat."},"level_min_cm":{"type":"integer","nullable":true},"level_max_cm":{"type":"integer","nullable":true},"orientativ":{"type":"boolean","description":"Marcajul G2 pentru zilele 4–5; în fereastra 24–72 h este `false`, păstrat pentru contract."}},"required":["day","horizon_h","level_cm","level_min_cm","level_max_cm","orientativ"]},"ApeMici":{"type":"object","description":"Răspunsul `/summary/low-water`: anul ales, anii de referință și câte un rând pe sector ( țara Dunării ).","properties":{"generated_at":{"type":"string","format":"date-time"},"year":{"type":"integer","nullable":true,"description":"Anul ales; `null` fără perioade sub LDC în rollup."},"reference_years":{"type":"array","items":{"type":"integer"},"description":"Anii marilor secete: 2003, 2015, 2018, 2022."},"sectors":{"type":"array","items":{"$ref":"#/components/schemas/SectorApaMica"}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["generated_at","year","reference_years","sectors","_attribution"]},"SectorApaMica":{"type":"object","description":"Un sector al Dunării într-un an: cea mai lungă perioadă neîntreruptă sub LDC a unei stații, stația record și comparația cu anii de referință.","properties":{"country":{"type":"string","nullable":true,"description":"Codul ISO al țării; `null` pentru stațiile fără țară."},"name":{"type":"string"},"year":{"type":"integer"},"max_consecutive_days":{"type":"integer","description":"Zilele perioadei record din sector."},"from":{"type":"string","description":"Prima zi a perioadei record (`YYYY-MM-DD`)."},"to":{"type":"string","description":"Ultima zi a perioadei record (`YYYY-MM-DD`)."},"station":{"type":"object","description":"Stația care deține perioada record.","properties":{"id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":"string"},"rkm":{"type":"number","nullable":true}},"required":["id","name","slug","rkm"]},"stations_below":{"type":"integer","description":"Stații cu cel puțin o perioadă sub LDC în an."},"station_days_below":{"type":"integer","description":"Zile-stație sub LDC ( toate perioadele, nu doar recordul )."},"windows":{"type":"integer","description":"Numărul perioadelor sub LDC din sector."},"history":{"type":"array","items":{"$ref":"#/components/schemas/AnApaMica"},"description":"Toți anii sectorului, cronologic."},"reference":{"type":"array","items":{"$ref":"#/components/schemas/ReferintaApaMica"},"description":"Anii de referință, cu diferența față de anul ales."}},"required":["country","name","year","max_consecutive_days","from","to","station","stations_below","station_days_below","windows","history","reference"]},"AnApaMica":{"type":"object","description":"Un an din istoricul unui sector: perioada record și zilele ei.","properties":{"year":{"type":"integer"},"max_consecutive_days":{"type":"integer"},"from":{"type":"string"},"to":{"type":"string"}},"required":["year","max_consecutive_days","from","to"]},"ReferintaApaMica":{"type":"object","description":"Un an de referință: perioada record de atunci și diferența în zile față de anul ales ( pozitiv = anul ales e mai secetos ).","properties":{"year":{"type":"integer"},"max_consecutive_days":{"type":"integer","nullable":true,"description":"`null` = anul nu are perioade sub LDC în date."},"from":{"type":"string","nullable":true},"to":{"type":"string","nullable":true},"delta_days":{"type":"integer","nullable":true}},"required":["year","max_consecutive_days","from","to","delta_days"]},"PrecipitatiiBazin":{"type":"object","description":"Răspunsul `/basin-precipitation`: sub-bazinele în ordinea catalogului, cu ploaia cumulată pe 24 / 72 h și legătura la stația din aval.","properties":{"generated_at":{"type":"string","format":"date-time"},"window_hours":{"type":"array","items":{"type":"integer"},"description":"Ferestrele cumulate, în ore: 24 și 72."},"sub_basins":{"type":"array","items":{"$ref":"#/components/schemas/SubBazinPrecipitatii"}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["generated_at","window_hours","sub_basins","_attribution"]},"SubBazinPrecipitatii":{"type":"object","description":"Un sub-bazin: ploaia cumulată la punctul de calcul ( stația de amonte ) și stația din aval de care se leagă semnalul.","properties":{"sub_basin":{"type":"string","example":"inn-amonte"},"name":{"type":"string","example":"Inn — amonte ( Tirol )"},"river":{"type":"string","example":"inn"},"point":{"type":"object","description":"Coordonatele punctului de calcul ( stația de pe cursul superior ).","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}},"required":["latitude","longitude"]},"window_end":{"type":"string","format":"date-time","description":"Momentul până la care sunt cumulate orele ( exclusiv )."},"precipitation_24h_mm":{"type":"number","description":"Precipitațiile cumulate în ultimele 24 h, în mm."},"precipitation_72h_mm":{"type":"number","description":"Precipitațiile cumulate în ultimele 72 h, în mm."},"hours_24h":{"type":"integer","description":"Câte ore cu valoare au intrat în fereastra de 24 h ( 24 = fereastră completă )."},"hours_72h":{"type":"integer","description":"Câte ore cu valoare au intrat în fereastra de 72 h ( 72 = fereastră completă )."},"downstream_station":{"type":"object","nullable":true,"description":"Stația din aval a sub-bazinului; `null` când legătura nu s-a putut face la scriere.","properties":{"slug":{"type":"string"},"name":{"type":"string"},"rkm":{"type":"number","nullable":true}},"required":["slug","name","rkm"]}},"required":["sub_basin","name","river","point","window_end","precipitation_24h_mm","precipitation_72h_mm","hours_24h","hours_72h","downstream_station"]},"AcuratetePrognoza":{"type":"object","description":"Backtest al prognozelor oficiale față de citirile reale, pe sursă × orizont ( +24 / +48 / +72 h ). `mae_cm` și `bias_cm` sunt în cm; `bias_cm` pozitiv înseamnă că prognoza a fost peste citire. `within_band_pct` se calculează doar pe eșantioanele cu bandă min–max publicată. `sources` are toate sursele cu prognoză în fereastră, inclusiv cele încă fără perechi prognoză–citire.","properties":{"station":{"type":"object","nullable":true,"description":"Stația cerută: `{slug, name}` pe `/stations/{slug}/forecast-accuracy` și pe `/forecast/accuracy?station=`; `null` doar pe agregatul bazinului.","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]},"period_days":{"type":"integer","description":"Fereastra backtestului, în zile după momentul țintă."},"horizons":{"type":"array","items":{"type":"integer"},"description":"Orizonturile din răspuns: 24, 48, 72."},"method":{"$ref":"#/components/schemas/MetodaAcuratete"},"sources":{"type":"array","items":{"$ref":"#/components/schemas/SursaAcuratete"}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["station","period_days","horizons","method","sources","_attribution"]},"MetodaAcuratete":{"type":"object","description":"Metoda backtestului, în engleză, ca restul contractului public.","properties":{"window_days":{"type":"integer"},"match_tolerance_hours":{"type":"integer","description":"Cât de departe poate fi citirea reală de momentul țintă."},"preferred_reading_source":{"type":"string"},"error_sign":{"type":"string"},"within_band_denominator":{"type":"string"}},"required":["window_days","match_tolerance_hours","preferred_reading_source","error_sign","within_band_denominator"]},"SursaAcuratete":{"type":"object","description":"Acuratețea unei surse emitente, pe cele trei orizonturi ( toate prezente ). O sursă care a prognozat, dar n-are încă nicio pereche prognoză–citire, apare cu `samples: 0` și mediile `null`.","properties":{"source":{"type":"string","example":"afdj"},"label":{"type":"string","example":"AFDJ"},"horizons":{"type":"array","items":{"$ref":"#/components/schemas/OrizontAcuratete"}}},"required":["source","label","horizons"]},"OrizontAcuratete":{"type":"object","description":"Statistica unui orizont: eșantioane, stații distincte cu perechi, MAE, bias și procentul în bandă. `samples: 0` înseamnă că sursa a prognozat la orizontul acela, dar nicio citire reală nu s-a potrivit în ±6 h ( mediile sunt `null` ).","properties":{"horizon_h":{"type":"integer","enum":[24,48,72]},"samples":{"type":"integer"},"stations":{"type":"integer"},"mae_cm":{"type":"number","nullable":true},"bias_cm":{"type":"number","nullable":true},"band_samples":{"type":"integer"},"within_band_pct":{"type":"number","nullable":true}},"required":["horizon_h","samples","stations","mae_cm","bias_cm","band_samples","within_band_pct"]},"Disponibilitate":{"type":"object","description":"Raportul „transparența datelor”: disponibilitatea lunară pe sursă, pe 12 luni calendaristice. Numai cifre.","properties":{"from":{"type":"string","format":"date","description":"Prima zi a ferestrei (întâi ale primei luni)."},"to":{"type":"string","format":"date","description":"Ultima zi încheiată (ieri, în fusul produsului)."},"months":{"type":"array","items":{"type":"string","example":"2026-10"},"description":"Cele 12 luni, cronologic."},"last_day_with_data":{"type":"string","format":"date","nullable":true,"description":"Ultima zi din fereastră cu date, din orice sursă; `null` când rollup-ul n-a avut nimic."},"sources":{"type":"array","items":{"$ref":"#/components/schemas/DisponibilitateSursa"}},"_attribution":{"$ref":"#/components/schemas/Atribuire"}},"required":["from","to","months","last_day_with_data","sources","_attribution"]},"DisponibilitateSursa":{"type":"object","description":"O sursă: lunile, totalul pe fereastră și cifrele ultimelor 7 zile din jurnalul Q62.","properties":{"source":{"type":"string","example":"afdj"},"source_name":{"type":"string","example":"AFDJ (RO)"},"active":{"type":"boolean","description":"`false` = sursa e oprită din panou; rămâne în raport."},"days":{"type":"integer","description":"Zilele socotite pe toată fereastra."},"days_with_data":{"type":"integer","description":"Zilele cu cel puțin o citire."},"percent":{"type":"number","nullable":true,"minimum":0,"maximum":100,"description":"Procentul zilelor cu date (o zecimală)."},"last_7_days":{"$ref":"#/components/schemas/DisponibilitateRulari"},"months":{"type":"array","items":{"$ref":"#/components/schemas/DisponibilitateLuna"}}},"required":["source","source_name","active","days","days_with_data","percent","last_7_days","months"]},"DisponibilitateLuna":{"type":"object","description":"O lună: zilele socotite (luna curentă doar până ieri) și zilele cu date.","properties":{"month":{"type":"string","example":"2026-10"},"days":{"type":"integer"},"days_with_data":{"type":"integer"},"percent":{"type":"number","nullable":true,"minimum":0,"maximum":100}},"required":["month","days","days_with_data","percent"]},"DisponibilitateRulari":{"type":"object","description":"Rulările și eșecurile ultimelor 7 zile, din jurnalul Q62 (`null` = fără jurnal).","properties":{"runs":{"type":"integer","nullable":true},"failures":{"type":"integer","nullable":true}},"required":["runs","failures"]},"ConfirmareAlerta":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"},"status":{"type":"string","enum":["confirmat","deja"],"description":"Lipsește pe un jeton invalid ( 404 )."},"active":{"type":"boolean","description":"Abonamentul e pornit după apel."},"error":{"type":"string","const":"invalid_token","description":"Doar pe 404: jeton străin sau expirat."}}},"Eroare":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}},"required":["error","message"]},"EroareCheie":{"type":"object","properties":{"error":{"type":"string","const":"invalid_api_key"},"reason":{"type":"string","enum":["malformed","unknown_or_revoked"]},"message":{"type":"string"},"docs":{"type":"string","format":"uri"}},"required":["error","reason","message"]},"EroareLimita":{"type":"object","properties":{"error":{"type":"string","const":"rate_limit_exceeded"},"retry_after_seconds":{"type":"integer"},"docs":{"type":"string","format":"uri"}},"required":["error","retry_after_seconds"]}}},"security":[{"cheie":[]},{}]}