oneapi
Sign in
Financiar v1 / Fiscal

Salary net to gross

The gross that produces a given net, with the same breakdown.

⚠️ It cannot be solved algebraically. Every component is rounded to the leu, so the gross → net function is constant over small intervals: several gross figures can give the same net, and some nets are not reachable from any whole gross. The route searches for the gross that gives EXACTLY the net requested, returns the smallest when there are several — and says in the response that there are several — and when there is none, refuses explicitly rather than rounding.

⚠️ When inverting, we do not know the gross until we have found it, so we do not know which allowance band it falls in either. We do not assume one: the engine is given a resolver and asks, for every candidate gross it tries, what allowance that gross carries. That keeps the inversion exact across the whole scale, not just above the threshold at which the allowance is zero.

POST
https://oneapi.ro/api/financiar/v1/calcul/salariu/net-la-brut

Request body

Sent as JSON in the request body (Content-Type: application/json) — not in the query string.

NameTypeDescriptionAccepted values
netrequired integer | null Required, in whole lei. 1 – 100000000
la_dataoptional string | null Optional, YYYY-MM-DD; defaults to today.
normaoptional string | null Optional: intreaga (default) or partiala. On part-time, contributions are computed against the minimum wage, not the actual gross. intreagapartiala
facilitateoptional string | null Optional, as in brut-la-net.
persoane_intretinereoptional integer | null Optional, 0-20. 0 – 20
deducere_personalaoptional integer | null Optional, in lei; required below the threshold the response indicates. 0 – 100000
3,000 lei net Request body
{
    "net": 3000
}
5,000 lei net Request body
{
    "net": 5000
}
With one dependant Request body
{
    "net": 4000,
    "persoane_intretinere": 1
}
The construction sector, in 2023 Request body
{
    "net": 10000,
    "facilitate": "constructii",
    "la_data": "2023-06-15"
}

Query parameters

This route accepts no query parameters.

How it behaves

  • The gross that yields a given net, with the same breakdown as brut-la-net.
  • ⚠️ It cannot be solved algebraically. Every component is rounded to the leu, so the gross → net function is constant over small intervals: several grosses can yield the same net, and some nets are reached by no whole gross at all. The route searches for the gross that yields exactly the requested net; where several do, it returns the smallest and lists them all in the response; where none does, it refuses with net_imposibil rather than rounding and appearing to have succeeded.
  • ⚠️ On inversion we do not know the gross before finding it, so we do not know which deduction bracket applies either. We do not assume one: the engine is handed a resolver and asks, for every candidate gross it tries, what deduction that gross carries. The inversion therefore stays exact across the whole grid, not only above the threshold where the deduction is zero. Example: a net of 2,695 lei on 1 March 2025 gives exactly 4,500 lei.
  • ⚠️ POST and zero retention, as with brut-la-net.

What it is for

  • Negotiating a salary from the net, with the corresponding gross cost.
  • Checking a payslip in reverse.

Response structure

FieldTypeDescription
data.net integer The computed net position: total assets minus total liabilities.
data.brut integer The smallest whole gross that yields exactly the requested net.
data.la_data string The date the returned values are valid on.
data.facilitate null
data.componente[].cod string Code from the source code list — the key you filter on.
data.componente[].denumire string The name, exactly as the source publishes it.
data.componente[].baza_de_calcul integer The amount the rate was applied to — for income tax it is the taxable base, not the gross.
data.componente[].cota string
data.componente[].valoare integer The value published by the source for the combination above.
data.componente[].act_normativ string The legal basis of the rate applied to that component.
data.componente[].de_verificat boolean
meta.sursa string The official source the data comes from, with its licence where one is required.
meta.retentie string Confirmation that the input was not stored anywhere.
meta.nota_acoperire string Why the total is a lower bound, in prose. meta.total_e_limita_de_jos is the word to switch on in code.
meta.avertismente array States, where applicable, that several grosses yield the same net, and which.
data.brut_interval Present only when the deduction falls in the untranscribed band: the bounds the gross certainly lies between. When present, brut is null.
meta.fara_date data is null and this says why. neacoperit, facilitate_inactiva.
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

body: {"net": 3000}

POSThttps://oneapi.ro/api/financiar/v1/calcul/salariu/net-la-brut
{
    "data": {
        "net": 3000,
        "brut": 5036,
        "la_data": "2026-10-07",
        "facilitate": null,
        "componente": [
            {
                "cod": "cas",
                "denumire": "Contribuţia de asigurări sociale",
                "baza_de_calcul": 5036,
                "cota": "25%",
                "valoare": 1259,
                "act_normativ": "Codul Fiscal art.138",
                "de_verificat": false
            }
        ]
    },
    "meta": {
        "sursa": "Cotele vin din registrul comun `business_indicatori_fiscali`; facilităţile şi grila deducerii, din `Modules/Financiar/resources/fiscal`, cu act normativ pe fiecare valoare.",
        "retentie": "Zero. Intrarea nu se scrie nicăieri — nici în bază, nici în cache, nici în log.",
        "nota_acoperire": "Ce e acoperit şi ce nu: /financiar/v1/fiscal/acoperire."
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatMissing or invalid token.
403feature_indisponibilfinanciar.fiscal_calcul is not in the current plan.
422net_imposibilNo whole gross yields this net. deducere_neacoperita — only for a la_data before 2023. net_lipsa.
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": "net_imposibil",
        "mesaj": "No whole gross yields this net. deducere_neacoperita — only for a la_data before 2023. net_lipsa."
    }
}