Financiar v1 / CursMediu
Average exchange rate (official NBR)
The official NBR average for a month (?luna=YYYY-MM), a quarter (?trimestru=YYYY-Qn, written 2024-T2) or a year (?an=YYYY), for every currency or a list (?valuta=EUR,USD). Without a period, the latest published month. The quarterly and yearly averages are built from the MONTHLY averages, not from the daily quotes — as the NBR publishes them; the response shows the components and what the intuitive method would give.
GET
https://oneapi.ro/api/financiar/v1/curs-mediu
Query parameters
NameTypeDescriptionAccepted values
lunaoptional
string | null
A month,
YYYY-MM, from 2005. With no period at all, the latest published month.
e.g. 2024-06
trimestruoptional
string | null
A quarter,
YYYY-Qn written as 2024-T2, like the central-bank label.
e.g. 2024-T2
anoptional
integer | null
A year,
YYYY, from 2005 up to the last completed and published year.
2005 – 2100
valutalistoptional
text
Optional filter:
?valuta=EUR,USD. Without it every currency of the period is returned.
e.g. EURe.g. EUR,USD
How it behaves
- The official central-bank average for a month (
?luna=YYYY-MM), a quarter (?trimestru=YYYY-Qn, written2024-T2) or a year (?an=YYYY) — only one. Without a period, the latest published month. The parameter sent sets the granularity, and the response takes its shape: quarters and years also carry the monthly components. - The monthly average exchange rate as published by NBR in its foreign-exchange market monthly series. This is the figure required in accounting and tax reporting.
- The official average IS the arithmetic mean of the daily quotes, rounded to four decimals. Not an assumption: verified across all 7,567 month×currency pairs since 2005, the maximum deviation is 0.00005 — exactly half a unit on the last decimal, the signature of rounding. So the route does not choose between two methodologies; it returns the published figure and shows the recomputation alongside.
verificareholds our own average recomputed from that month's daily quotes, the number of banking days that went into it, and the difference from the official figure. The result is verifiable without reproducing the logic — and you can see what it was computed over.- Values are RON per ONE unit of currency. The monthly series is already divided by the multiplier, unlike
/curs, where five currencies are published per 100: the yen appears here as0.02823, not2.823. That is why the response has nomultiplicatorfield — there would be nothing to apply, and its presence would invite the wrong multiplication. - The current month returns 404 with
luna_neincheiata, not a partial average. An average over an unfinished month looks exactly like a final one and gets quoted the same way, so it is not returned at all. The code is distinct fromnepublicata, which means "the month ended, but NBR has not published it yet". - Coverage starts in January 2005. There is no official average for earlier periods — the currency was the old leu, and the monthly series begin with the new one. The average of the daily quotes from then can be computed from
/curs-istoric/interval, but it is your figure, not a published one. - Without a filter, every currency with a published average for that month is returned. The count varies over time: delisted currencies (BGN from 2026) disappear from later months.
- The quarterly average exchange rate as published by NBR in its foreign-exchange market quarterly series.
- It is not the mean of the quarter's daily quotes, but the mean of the THREE MONTHLY AVERAGES. Verified across 2,502 quarter×currency pairs: a 100% match with the mean-of-means (maximum deviation 0.000033, i.e. rounding) against only 36.9% with the daily mean. Anyone computing "the average EUR rate for Q1" from daily quotes gets a different number than the official one.
- The difference comes from weighting, and it is common, not exotic. The mean of means weights the months equally; the daily mean weights them by their number of banking days, which varies. Result: 70.4% of pairs deviate by more than 0.01%, the median is 0.0226%, and in volatile quarters it reaches ~0.9% — the rouble in Q1 2022 (0.0519 official against 0.051427 from daily quotes), the Turkish lira in Q2 2006, the Egyptian pound in Q4 2016.
construita_dinshows the real construction: the three monthly averages, their mean, and the difference from the published figure.din_zilniceshows what the intuitive method would produce, with the difference from the official value. The second is not an alternative correct answer — it is the trap, put in plain sight precisely so it is not used by accident.- The current quarter returns 404 with
trimestru_neincheiat, not an average over two months out of three. It would look exactly like a final one and be quoted the same way. The code is distinct fromnepublicata, which means "it ended, but NBR has not published it yet". - Values are RON per ONE unit of currency, already divided by the multiplier — as in the monthly series, and unlike
/curs. - Coverage starts with Q1 2005.
- The annual average exchange rate as published by NBR in its foreign-exchange market annual series. This is the figure for annual filings and balance-sheet conversions.
- It is the mean of the TWELVE monthly averages, as with quarters but taken further. Verified across 597 year×currency pairs: a 100% match with the mean of the 12 months, 98.5% with the mean of the 4 quarters, and only 27.6% with the mean of daily quotes.
- The mean of the four quarterly values is not a second method. It yields the same result mathematically — each quarter holds exactly 3 months, weighted equally — but deviates in 1.5% of cases because the quarterly values are rounded to 4 decimals before being averaged. It is the same construction with one extra rounding step.
- The trap is larger than at quarter level: the maximum deviation from the daily mean reaches 1.07 — over one leu. The longer the period, the more the difference in monthly weighting accumulates.
construita_dinshows the real construction: the twelve monthly averages, their mean, and the difference from the published figure.din_zilniceshows what the intuitive method would produce. The second is not an alternative correct answer — it is the trap, in plain sight.- The components are always present, whether or not you filter by currency. Without a filter the response holds 40 currencies × 12 months, roughly 20 KB — a route that changes its structure depending on a parameter is harder to use than one that is slightly larger.
- The current year returns 404 with
an_neincheiat, not a partial average. The code is distinct fromnepublicata, which means "the year ended, but NBR has not published it yet". - Values are RON per ONE unit of currency, already divided by the multiplier. Coverage starts in 2005.
What it is for
- The monthly average rate for an accounting or tax filing.
- Converting a month's income or expense flow.
- Checking a figure someone else used, with the recomputation next to it.
- The quarterly average rate for a filing or an interim financial statement.
- Checking a quarterly figure wrongly computed from daily quotes.
- Converting a quarterly income or expense flow.
- The annual average rate for financial statements and year-end filings.
- Converting an annual income or expense flow.
- Checking an annual figure wrongly computed from daily quotes.
Response structure
FieldTypeDescription
data.luna
string
The month the data refers to.
data.de_la
string
First day of the month.
data.pana_la
string
Last day of the month.
data.moneda_baza
string
The currency the rates are quoted against.
data.medii[].valuta
string
ISO 4217 currency code.
data.medii[].denumire
string
The name, exactly as the source publishes it.
data.medii[].valoare_unitara
string
The official NBR average, RON per ONE unit of currency. The figure to quote.
data.medii[].verificare.medie_din_zilnice
string
Our recomputation from the month's daily quotes.
data.medii[].verificare.zile_bancare
integer
How many days actually entered the average.
data.medii[].verificare.diferenta
string
Official minus recomputed. Always below 0.00005 — rounding, not methodology.
meta.sursa
string
The official source the data comes from, with its licence where one is required.
meta.acoperire.de_la
string
The first period we have data for.
meta.acoperire.pana_la
string
The last period we have data for.
meta.valute
integer
Currencies covered by the response.
meta.nota_unitate
string
What to know about the unit of measure before comparing or summing values.
meta.nota_verificare
string
A note on how to read the response: a caveat, a convention or a limit of the source.
meta.zilnic
string
meta.fara_valori
Currencies requested through the filter that have no average for that month.
meta.fara_date
data is null and this says why. The series are not in the database. The period is still being written, it is before 2005, or none of the requested currencies has a published average.
meta.fara_date_cod
The short, STABLE word for the reason, for clients that branch on it in code:
fara_date is prose and may be rephrased, this is not.
Response examples
GEThttps://oneapi.ro/api/financiar/v1/curs-mediu?valuta=EUR
{
"data": {
"luna": "2026-08",
"de_la": "2026-08-01",
"pana_la": "2026-08-31",
"moneda_baza": "RON",
"medii": [
{
"valuta": "EUR",
"denumire": "Euro",
"valoare_unitara": "5.2498",
"verificare": {
"medie_din_zilnice": "5.24978571",
"zile_bancare": 21,
"diferenta": "0.00001429"
}
}
]
},
"meta": {
"sursa": "BNR — cursul de schimb al pieţei valutare, serii lunare (baza de date interactivă).",
"acoperire": {
"de_la": "2005-01",
"pana_la": "2026-08"
},
"valute": 1,
"nota_unitate": "Valorile sunt RON pentru O unitate de valută, deja împărţite la multiplicator — spre deosebire de `/curs`, unde cinci valute se publică la 100.",
"nota_verificare": "Media oficială e media aritmetică a cotaţiilor zilnice, rotunjită la 4 zecimale. `verificare` conţine recalcularea noastră şi diferenţa; verificat pe toată seria, abaterea maximă e 0,00005.",
"zilnic": "Cotaţiile zi cu zi ale aceleiaşi luni: /financiar/v1/curs/interval?valuta=EUR&de_la=2026-08-01&pana_la=2026-08-31"
}
}
GEThttps://oneapi.ro/api/financiar/v1/curs-mediu?luna=2024-06&valuta=EUR,USD
{
"data": {
"luna": "2024-06",
"de_la": "2024-06-01",
"pana_la": "2024-06-30",
"moneda_baza": "RON",
"medii": [
{
"valuta": "EUR",
"denumire": "Euro",
"valoare_unitara": "4.9766",
"verificare": {
"medie_din_zilnice": "4.97657368",
"zile_bancare": 19,
"diferenta": "0.00002632"
}
}
]
},
"meta": {
"sursa": "BNR — cursul de schimb al pieţei valutare, serii lunare (baza de date interactivă).",
"acoperire": {
"de_la": "2005-01",
"pana_la": "2026-08"
},
"valute": 2,
"nota_unitate": "Valorile sunt RON pentru O unitate de valută, deja împărţite la multiplicator — spre deosebire de `/curs`, unde cinci valute se publică la 100.",
"nota_verificare": "Media oficială e media aritmetică a cotaţiilor zilnice, rotunjită la 4 zecimale. `verificare` conţine recalcularea noastră şi diferenţa; verificat pe toată seria, abaterea maximă e 0,00005.",
"zilnic": "Cotaţiile zi cu zi ale aceleiaşi luni: /financiar/v1/curs/interval?valuta=EUR&de_la=2024-06-01&pana_la=2024-06-30"
}
}
GEThttps://oneapi.ro/api/financiar/v1/curs-mediu?trimestru=2024-T2&valuta=EUR
{
"data": {
"trimestru": "2024-T2",
"de_la": "2024-04-01",
"pana_la": "2024-06-30",
"moneda_baza": "RON",
"medii": [
{
"valuta": "EUR",
"denumire": "Euro",
"valoare_unitara": "4.9751",
"construita_din": {
"luni": [
{
"luna": "2024-04",
"valoare_unitara": "4.973"
}
],
"medie_de_medii": "4.97513333",
"diferenta": "-0.00003333"
},
"din_zilnice": {
"medie": "4.97501639",
"zile_bancare": 61,
"diferenta_fata_de_oficial": "0.00008361"
}
}
]
},
"meta": {
"sursa": "BNR — cursul de schimb al pieţei valutare, serii trimestriale (baza de date interactivă).",
"acoperire": {
"de_la": "2005-T1",
"pana_la": "2026-T2"
},
"valute": 1,
"nota_constructie": "Media trimestrială oficială e media celor trei medii LUNARE, nu media cotaţiilor zilnice. `construita_din` arată componentele; `din_zilnice` arată ce ar ieşi din metoda intuitivă, cu diferenţa.",
"nota_divergenta": "Cele două metode diferă cu peste 0,01% în 70,4% dintre cazuri (mediana 0,0226%); în trimestrele volatile diferenţa urcă la ~0,9%.",
"nota_unitate": "Valorile sunt RON pentru O unitate de valută, deja împărţite la multiplicator.",
"lunar": "Mediile lunare care compun cifra: /financiar/v1/curs-mediu?luna=AAAA-LL."
}
}
GEThttps://oneapi.ro/api/financiar/v1/curs-mediu?an=2024&valuta=EUR
{
"data": {
"an": "2024",
"de_la": "2024-01-01",
"pana_la": "2024-12-31",
"moneda_baza": "RON",
"medii": [
{
"valuta": "EUR",
"denumire": "Euro",
"valoare_unitara": "4.9746",
"construita_din": {
"luni": [
{
"luna": "2024-01",
"valoare_unitara": "4.9748"
}
],
"luni_folosite": 12,
"medie_de_medii": "4.9746",
"diferenta": "0"
},
"din_zilnice": {
"medie": "4.97456071",
"zile_bancare": 252,
"diferenta_fata_de_oficial": "0.00003929"
}
}
]
},
"meta": {
"sursa": "BNR — cursul de schimb al pieţei valutare, serii anuale (baza de date interactivă).",
"acoperire": {
"de_la": "2005",
"pana_la": "2025"
},
"valute": 1,
"nota_constructie": "Media anuală oficială e media celor douăsprezece medii LUNARE, nu media cotaţiilor zilnice. `construita_din` arată componentele; `din_zilnice` arată ce ar ieşi din metoda intuitivă, cu diferenţa.",
"nota_divergenta": "Media zilnicelor se potriveşte cu cifra oficială în doar 27,6% dintre cazuri; abaterea maximă măsurată e 1,07.",
"nota_trimestre": "Media celor patru valori trimestriale dă acelaşi rezultat matematic, dar se abate în 1,5% din cazuri din cauza rotunjirii lor prealabile. Nu e o a doua metodă.",
"nota_unitate": "Valorile sunt RON pentru O unitate de valută, deja împărţite la multiplicator.",
"lunar": "Mediile lunare care compun cifra: /financiar/v1/curs-mediu?luna=AAAA-LL."
}
}
Error codes
| Code | Slug | When it occurs |
|---|---|---|
| 401 | neautentificat | Token missing, invalid, expired or revoked. |
| 403 | feature_indisponibil | The current plan does not include the feature the route depends on. |
| 422 | validare | Several periods at once (luna, trimestru, an do not combine), a period written other than YYYY-MM, YYYY-Tn or YYYY, a period before 2005 (in old lei: /curs-istoric/mediu), an invalid currency code. |
| 429 | cota_depasita | The plan's monthly quota has been exceeded (see Retry-After). |
All errors share the same shape. eroare.cod is stable and is the value you should branch on in code — not the text in mesaj, which may change.
{
"eroare": {
"cod": "validare",
"mesaj": "Several periods at once (luna, trimestru, an do not combine), a period written other than YYYY-MM, YYYY-Tn or YYYY, a period before 2005 (in old lei: /curs-istoric/mediu), an invalid currency code.",
"detalii": {
"luna": [
"The value sent does not satisfy the parameter rule."
]
}
}
}