oneapi
Sign in
Financiar v1 / Calcul

Foreign exchange differences

The gain or loss on exchange for an amount in foreign currency, between two dates, at the official NBR rate.

The same rate movement gives opposite results depending on what you hold. On 100,000 EUR, between January 2025 and August 2026, the rate rose by 0.2786 lei — 27,860 lei. On a receivable that is a gain: you collect more lei. On a payable it is a loss: you pay more. The figure is identical, the sign is reversed.

That is why pozitie is required, with no default: a default would silently make half the answers wrong.

The quotations follow the rules of /curs: a day with no publication takes the last previous quotation, flagged with exact: false and zile_inapoi. The same day at both ends gives a zero difference, not an error — anyone running a report over a list of invoices should not have to special-case it.

cont_orientativ gives the account from the general chart (765 favourable, 665 unfavourable). It is indicative: the classification depends on accounting policy and on the nature of the transaction, not on our data.

GET
https://oneapi.ro/api/financiar/v1/calcul/diferente-curs

Query parameters

NameTypeDescriptionAccepted values
sumarequired string Required. The amount in foreign currency, at most 6 decimals. e.g. 1000e.g. 2500.75e.g. 10000
valutarequired string Required. Three-letter code (EUR, USD). max 3 car.
pozitierequired string Required: creanta (you are owed) or datorie (you owe). No default. creantadatorie
de_larequired string Required, YYYY-MM-DD. The initial date — typically the invoice date. e.g. 2024-06-15e.g. 2024-01-15
pana_larequired string Required, YYYY-MM-DD. The final date — typically collection or payment. May equal de_la. e.g. 2024-06-15e.g. 2024-06-14

How it behaves

  • The exchange gain or loss on a foreign-currency amount, between two dates, at the official NBR rate.
  • The same rate movement produces OPPOSITE results depending on what you hold. On EUR 100,000, between January 2025 and August 2026, the rate rose by 0.2786 lei — RON 27,860. On a receivable that is a gain: you collect more lei. On a payable it is a loss: you pay more. The figure is identical, the sign is reversed, and this is where the mistake is most often made.
  • pozitie is required, with no default. A default would silently make half the answers wrong, and the mistake would not stand out: the figure would be right in magnitude. The same decision as tip on /termen/civil, where the absence of a default is deliberate because the choice changes the result.
  • diferenta.valoare is the ACCOUNTING figure, signed according to the position. diferenta.variatie_valoare_lei is the plain change in the lei value, the same regardless of position — both are in the response precisely so the relationship between them is visible.
  • Quotes follow the /curs rules: a day without publication receives the last preceding quote, marked with exact: false and zile_inapoi, separately at each end. Quotes are never invented and the substitution is never hidden.
  • The same day at both ends gives a zero difference, not an error. Anyone running a report over a list of invoices need not special-case it. The kind is then neutra, and no account is given.
  • cont_orientativ gives the account from the Romanian general chart (Order 1802/2014): 765 for favourable differences, 665 for unfavourable. It is indicative, and marked as such: the classification depends on accounting policy and on the nature of the operation — settlement or revaluation — not on our data.
  • Partial payments and instalment settlements are not handled: one amount, two dates. A stream of payments is a different question with a different response shape.
  • To revalue a BALANCE at period end, the closing rate is used rather than that of an arbitrary day: /curs-inchidere?luna=YYYY-MM.

What it is for

  • The exchange difference on collecting an invoice issued in foreign currency.
  • The difference on settling a foreign-currency payable.
  • Checking the sign in someone else's calculation.

Response structure

FieldTypeDescription
data.suma string Sum of the values, in the unit indicated alongside.
data.valuta string ISO 4217 currency code.
data.pozitie string Position of the item in the response order.
data.initial.data_ceruta string The date the client asked for, before alignment to a day that has data.
data.initial.data_cotatiei string
data.initial.exact boolean false when the requested day had no publication and an earlier one was used.
data.initial.zile_inapoi integer
data.initial.curs string The rate used at the first date, RON per one unit.
data.initial.valoare_lei string
data.final.data_ceruta string The date the client asked for, before alignment to a day that has data.
data.final.data_cotatiei string
data.final.exact boolean
data.final.zile_inapoi integer
data.final.curs string
data.final.valoare_lei string The lei value of the amount at the second date.
data.miscare_curs.lei_pe_unitate string How much the rate moved, in lei per unit of currency.
data.miscare_curs.procent string The same movement, in percent.
data.diferenta.valoare string The accounting difference, signed according to the position.
data.diferenta.valoare_exacta string
data.diferenta.fel string favorabila, nefavorabila or neutra.
data.diferenta.variatie_valoare_lei string The gross change in lei value, without the position sign.
data.diferenta.cont_orientativ null 765 or 665. Indicative — see the note.
meta.sursa string The official source the data comes from, with its licence where one is required.
meta.nota_pozitie string A note on how to read the response: a caveat, a convention or a limit of the source.
meta.nota_substituire string When and with what a missing value was substituted.
meta.reevaluare string
meta.fara_date data is null and this says why. The quote exists at the NBR, but our import is behind. The requested date is before 2005-01-03, where quotes are in old lei.
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/calcul/diferente-curs?suma=1000&valuta=EUR&pozitie=creanta&de_la=2024-06-15&pana_la=2024-06-15
{
    "data": {
        "suma": "1000",
        "valuta": "EUR",
        "pozitie": "creanta",
        "initial": {
            "data_ceruta": "2024-06-15",
            "data_cotatiei": "2024-06-14",
            "exact": false,
            "zile_inapoi": 1,
            "curs": "4.9771",
            "valoare_lei": "4977.10"
        },
        "final": {
            "data_ceruta": "2024-06-15",
            "data_cotatiei": "2024-06-14",
            "exact": false,
            "zile_inapoi": 1,
            "curs": "4.9771",
            "valoare_lei": "4977.10"
        },
        "miscare_curs": {
            "lei_pe_unitate": "0",
            "procent": "0.00"
        },
        "diferenta": {
            "valoare": "0.00",
            "valoare_exacta": "0",
            "fel": "neutra",
            "variatie_valoare_lei": "0.00",
            "cont_orientativ": null
        }
    },
    "meta": {
        "sursa": "BNR — cursul de referinţă.",
        "nota_pozitie": "Cursul nu s-a mişcat între cele două date: diferenţa e zero, indiferent de poziţie.",
        "nota_substituire": "Cel puţin una dintre zile n-a avut publicare; s-a folosit ultima cotaţie anterioară. Vezi `exact` şi `zile_inapoi` la fiecare capăt.",
        "reevaluare": "Pentru reevaluarea unui sold la închiderea perioadei se foloseşte cursul de închidere: /financiar/v1/curs-inchidere?luna=AAAA-LL."
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
404negasitThe currency was never quoted; delistata — no longer quoted, with the last day.
422validareMissing or invalid pozitie; malformed amount, currency or dates; future date; pana_la before de_la.
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": "Missing or invalid pozitie; malformed amount, currency or dates; future date; pana_la before de_la.",
        "detalii": {
            "suma": [
                "The value sent does not satisfy the parameter rule."
            ]
        }
    }
}