oneapi
Sign in
Financiar v1 / Bce

Conversion at ECB rates

Converts an amount using the European Central Bank's reference rates, without going through the leu.

The status of the result is not the same across all pairs, and the response declares it every time. When one side is EUR, the rate is the one the ECB actually PUBLISHES — oficial: true. When neither side is the euro, the result is a CROSS rate, computed through the euro: the ECB publishes EUR/USD and EUR/GBP, not USD/GBP. Then oficial: false and prin: "EUR".

The difference from /conversie/incrucisata is real, not merely one of status. USD/GBP computed through the euro differs from the same rate computed through the leu by 0.107% on average and by up to 1.15% — on 100,000 USD, more than a thousand lei. They are two independent fixings, and the route through the leu requires two conversions instead of one.

The direction is the OPPOSITE of the NBR's: the ECB quotes units of currency for 1 EUR, not lei for one unit. sens and componente are in every response precisely because inverting them inverts the result.

Both quotations come from the SAME day — the search is for the last day on which every requested currency has a quotation, not the last day of each. A cross rate spanning two market days is plausible and wrong.

The leu has no special status here: RON is a currency like any other in the ECB table.

GET
https://oneapi.ro/api/financiar/v1/bce/conversie

Query parameters

NameTypeDescriptionAccepted values
sumarequired string Required. Decimal point, at most 6 decimals. Negatives are allowed. e.g. 1000e.g. 250
dinrequired string Required. Three-letter code; EUR and RON are accepted like any other. max 3 car.
inrequired string Required. Three-letter code. max 3 car.
dataoptional string | null Optional, YYYY-MM-DD. Defaults to the current day. Cannot be in the future. e.g. 2024-06-15e.g. 2024-03-15

How it behaves

  • Converts an amount using the European Central Bank reference rates, without passing through the leu.
  • The status of the result is NOT the same for every pair, and the response declares it each time. When one side is EUR, the rate is the one actually PUBLISHED by the ECB: oficial: true. When neither side is the euro, the result is a CROSS rate — the ECB publishes EUR/USD and EUR/GBP, not USD/GBP — so oficial: false and prin: "EUR".
  • The difference from /conversie/incrucisata is real, not merely one of status. There the path goes through the leu, with NBR rates. Measured across shared days, USD/GBP via the euro differs from the same cross via the leu by 0.107% on average and up to 1.15% — on USD 100,000, more than a thousand lei. They are two independent fixings, and the route through the leu requires two conversions instead of one.
  • The direction is the INVERSE of NBR. The ECB quotes "units of currency per 1 EUR"; NBR quotes "lei per one unit of currency". Confusing them inverts the result, which is why sens and componente are in every response, with the raw quotes used.
  • Both quotes come from the SAME day. The search looks for the last day on which ALL requested currencies have a quote, not the last day of each — a cross rate between two market days is plausible and wrong. Any substitution is reported through exact and zile_inapoi.
  • The leu has no special status here: RON is a currency like any other in the ECB table, also quoted per euro. A RON → USD conversion through the euro is legitimate and gives a different result than one at the NBR rate — both correct, from different sources.
  • Identical currencies on both sides: the amount passes through unchanged, with factor: "1", no quote and no date. Not an error — a client converting a list need not special-case it.
  • Coverage: 44 currencies, since 1999. For the full list and the day's quotes, see /bce/curs.

What it is for

  • EUR ↔ currency conversion at the official ECB rate.
  • A parity between two foreign currencies, without the detour through the leu.
  • Comparing the result with the one obtained through NBR rates.

Response structure

FieldTypeDescription
data.suma string Sum of the values, in the unit indicated alongside.
data.din string
data.in string
data.data_ceruta string The date the client asked for, before alignment to a day that has data.
data.data string
data.exact boolean true only if the day returned is the one requested.
data.zile_inapoi integer How many days were stepped back for all currencies to have a quote on the same day.
data.oficial boolean true when one side is EUR — the rate is published by the ECB. false for crosses.
data.prin null EUR for cross rates; null when the result is official.
data.sens string Always valuta_per_1_eur — the ECB convention, the inverse of NBR.
data.factor string The number the amount was multiplied by: suma × factor = suma_convertita_exacta.
data.componente[].valuta string ISO 4217 currency code.
data.componente[].denumire null The name, exactly as the source publishes it.
data.componente[].unitati_per_eur string The raw ECB quote used, for each non-euro currency.
data.suma_convertita string
data.suma_convertita_exacta string
meta.sursa string The official source the data comes from, with its licence where one is required.
meta.sens string Direction of the operation.
meta.statut string The state the item is in at the source.
meta.fata_de_bnr string
meta.contract string
meta.nota_substituire string When and with what a missing value was substituted.
meta.fara_date data is null and this says why. One of the currencies is not quoted by the ECB, or there is no common day within the last 10 days.
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/bce/conversie?suma=1000&din=EUR&in=RON&data=2024-06-15
{
    "data": {
        "suma": "1000",
        "din": "EUR",
        "in": "RON",
        "data_ceruta": "2024-06-15",
        "data": "2024-06-14",
        "exact": false,
        "zile_inapoi": 1,
        "oficial": true,
        "prin": null,
        "sens": "valuta_per_1_eur",
        "factor": "4.9773",
        "componente": [
            {
                "valuta": "RON",
                "denumire": null,
                "unitati_per_eur": "4.9773"
            }
        ],
        "suma_convertita": "4977.30",
        "suma_convertita_exacta": "4977.3"
    },
    "meta": {
        "sursa": "Banca Centrală Europeană — cursuri de referinţă.",
        "sens": "Cotaţiile BCE sunt „unităţi de valută pentru 1 EUR\", INVERS faţă de BNR care cotează lei pentru o unitate de valută.",
        "statut": "Curs PUBLICAT de BCE: una dintre laturi e euro.",
        "fata_de_bnr": "Prin leu, cu cursurile BNR, acelaşi curs încrucişat diferă cu circa 0,1% în medie şi până la 1,15%: /financiar/v1/conversie/incrucisata.",
        "contract": "suma × factor = suma_convertita_exacta, cifră cu cifră.",
        "nota_substituire": "Ziua cerută nu are publicare la toate valutele; s-a folosit ultima zi în care toate aveau cotaţie."
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
422validareMalformed amount or currency code; future date.
429cota_depasitaThe 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": "Malformed amount or currency code; future date.",
        "detalii": {
            "suma": [
                "The value sent does not satisfy the parameter rule."
            ]
        }
    }
}