Skip to content

D101 — annual corporate profit tax

Annual corporate profit-tax return (declarația privind impozitul pe profit). This file is a completion guide: what the declaration settles, who files it and when, and how each form row maps onto the wire attribute anafpy authors — followed by the technical wire/DUK layer. ANAF's validator jar (D101Validator.jar) and the published structure annex are the authority; this guide is a distilled bridge, not a re-implementation of the rules. The instances below were proven hands-on on 2026-07-17 against D101Validator.jar J11.0.3 (feed directory D101_56, PDF jar P10.0.0).

The D101 is the annual self-assessment of corporate profit tax (impozit pe profit). It walks the accounting result to the fiscal result and then to the tax: accounting gross result (income − expense) → income-like / expense-like elementsfiscal deductions and non-taxable incomenon-deductible expensesfiscal result (taxable profit or loss) → loss carry-forward adjustment16% taxfiscal credits and reductionscomparison with the minimum turnover tax (IMCA)annual reconciliation against the quarterly advances / amounts already declared on D100. The result is a difference to pay (P52) or to recover (P53).

  • Legal basis: Title II of the Fiscal Code (Legea 227/2015), art. 13–46; the annual return and its deadline are art. 42. The row set implements the 2024 normative changes: the minimum turnover tax (IMCA, art. 18¹, introduced by Legea 296/2023), the fiscal-loss 70% / 5-year cap (art. 31(4¹), Legea 296/2023), and the R&D super-deduction credit (P43a, OUG 115/2024).
  • Current model: approved by OPANAF 206/2025 (M.Of. 11.02.2025), used for fiscal years ending ≥ 2024. universalCode D101_A600, wire generations v9 / v10. The structure annex was corrected 26.01.2026 (the scadenta formula) — a cached older annex or instructions PDF would silently poison the deadline and the nr_evid; see Special attention & gotchas.
  • Periodicity: annual — one filing per fiscal year (calendar year for most; a modified fiscal year is carried by Data_I/Data_S and the *_an_modif / Data_M attributes).

Who files & when

  • Who: profit-tax payers — Romanian legal persons on the profit-tax regime (not micro-enterprises, not those on a specific tax), and foreign legal persons with a Romanian permanent establishment or taxable Romanian-source income. The cod_obligatie picks the sub-type: 103 ordinary Romanian legal person (the SME default), 102 the advance-payment system (mandatory for banks, optional for others), 104 annual profit tax for agricultural co-ops / NGOs, 105 foreign legal persons. Banks and other BNR/ASF-regulated entities set d_reglem="1". A company that exited the micro-enterprise regime mid-year files a D101 for the profit-tax part of the year (trim_micro).
  • Deadline: the standard deadline is 25 March of the year following the fiscal year (art. 42). But during the OUG 153/2020 application window — fiscal years 2021–2025 — the deadline is pushed to 25 June of the following year, so FY2025 → 25 June 2026. The validator encodes exactly this: its scadenta rule adds +6 months for reporting years 2022–2025 (and 2021-December), and DUK computes 25.06.2026 for a calendar-year FY2025 return. Special cases: 25 February for art. 41(5)(a)/(b) taxpayers; for a modified fiscal year, the 25th of the sixth month from the fiscal-year close; BNR/ASF entities (d_reglem="1") and cod_obligatie="105" keep the +3 months (25 March) term; cod_obligatie="104" uses +2 months; a dissolution/liquidation date (Data_L/Data_B) adds one more month. The 25 June deadline is confirmed two independent ways: the validator scadenta formula (ANAF structure annex + D101IstoriaVersiunilor.txt) and the practitioner/legal sources that tie it to OUG 153/2020.
  • Corrections: refile a complete corrected D101d_rec="1" (rectificativă), or d_rec="2" (rectificativă ca urmare a unei notificări de conformare, paired with d_recN="1"). A declaration filed after annulment of the verification reserve sets d_anulare="1" with temei (1 = art. 105(6)(a), 2 = art. 105(6)(b) of L207/2015).

Filling guide

The document is one empty XML element<declaratie101>, everything an attribute, no children (the same shape as D300). There are two kinds of attribute: the identification & period block and the numbered money rows P1…P53 (with lettered sub-rows P081, P411, P421, …). All money rows are optional and default to absent = zero; a nil return carries only the identification block.

Author from the structure annex, not the published XSD. Every XSD ANAF publishes for D101 declares namespace …:v3, while the live wire format is mfp:anaf:dgti:d101:declaratie:v10. The structure annex PDF (structura_D101_2025_260126.pdf, universalCode D101_A600, v9 v10) is the authoritative attribute list, formats, and per-row formulas — it is aligned with the wire, the XSD is not. See the verbatim technical section below for how the undocumented format was recovered.

Identification & period block

Attribute Form field Notes
d_rec Declarație rectificativă 0 inițială / 1 rectificativă / 2 rect. cu notificare (d_rec=2 iff d_recN=1)
d_recN Rectificativă ca urmare a unei notificări de conformare 1 or null
d_reg Opțiunea privind regularizarea impozitului (art. 116¹) 0/1; 1 needs Stat_rezid (EU nomenclature N1) and a .zip attachment
Stat_rezid Stat de rezidență 2-char EU code (nomenclature N1), required when d_reg=1
d_anulare Declarație după anularea rezervei verificării 0/1
temei Temeiul legal al corectării 1/2 (art. 105(6)(a)/(b) L207/2015); required when d_anulare=1
d_succ Declarație depusă potrivit art. 90(4) L207/2015 (succesor) 0/1
cifS (XSD cifs) Cod de identificare fiscală succesor required when d_succ=1; CF/CNP-validated
d_alte 'Alte situații' 0/1; 1 frees Data_I/Data_S from the derived-date checks
d_reglem Contribuabil cu reglementări contabile B.N.R. / A.S.F. 0 = ordinary company, 1 = bank/insurer — see pitfalls
d_grup Membru de grup fiscal 1; zeroes the P48/P50/P52/P53 settlement rows
cod_obligatie Tip impozit pe profit (nomenclator) enum 102/103/104/105not 101; see pitfalls
luna_i / an_i Luna / anul de început de exercițiu financiar = Luna/Anul(Data_I); an_i ≥ 2024 (v10)
luna / an Luna / anul de sfârșit de exercițiu financiar = Luna/Anul(Data_S); an ≥ 2024
d_prof (micro→profit 2017 flag) deprecated — "nu se mai folosește"; omit it
trim_micro Trimestrul trecerii de la micro la profit 14; null for cod_obligatie=102; drives the D100↔D101 correlation
primul_an_modif / ultimul_an_modif Primul / ultimul an fiscal modificat 0/1; null for cod_obligatie=102
Data_M Data de început de an modificat D(10) dotted; null for cod_obligatie=102
Data_L / Data_B Data dizolvării cu / fără lichidare D(10); mutually exclusive; each adds +1 month to scadenta
Data_I / Data_S Data de început / sfârșit de exercițiu financiar capitalized, dotted dd.mm.yyyy (v3-XSD's lowercase data_i is wrong for v10)
scadenta Scadența plății C(6) ZZLLAA, computed — see pitfalls
cod_bug Cod bugetar C(10); annex families 20470101XX / 5503XXXXXX; content not validated by DUK
nr_evid Nr. de evidență a plății N(23), prefix 11, checksum — layout differs from D300; see pitfalls
totalPlata_A Suma de control control sum over P1…P53, not the tax payable — see pitfalls
nume_declar / prenume_declar / functie_declar declarant required text
cif Cod de identificare fiscală N(10); CIF check-digit enforced by the jar
caen Cod CAEN N(4); validated against the CAEN list (01.01.2025)
denumire / adresa Denumire / adresă required; telefon/fax/email optional
cifR / denR / adrR / telR / faxR / emailR împuternicit (representative) optional; cifR CF(10)/CIF(13)-validated

cod_obligatie nomenclature (from the annex; the jar rejects 101):

Code Creanță fiscală
102 Plăți anticipate în contul impozitului pe profit anual (bănci, PJ române, sucursale ale băncilor străine)
103 Impozit pe profit datorat de PJ române, altele decât cele de la 102 — the ordinary company
104 Impozit pe profit anual (cooperative agricole, ONG-uri) — no D100 is filed for this type
105 Impozit pe profit datorat de PJ străine, altele decât cele de la 102

Profit-tax computation rows → attributes

The money rows are a single cascade; every derived row carries a formula the jar enforces (ERR calcul on a mismatch). Sub-rows (the "din care" breakdowns) are indented under their parent and are excluded from the control sum.

Attr Field Formula / rule
P1 / P2 Venituri / cheltuieli de exploatare ≥ 0
P3 Rezultat din exploatare P3 = P1 − P2
P4 / P5 Venituri / cheltuieli financiare ≥ 0
P6 Rezultat financiar P6 = P4 − P5
P7 Rezultat brut (rezultat contabil) P7 = P3 + P6
P8 (P081/P082/P083/P084) Elemente similare veniturilor P8 ≥ ΣP08x
P9 (P091) Elemente similare cheltuielilor P9 ≥ P091
P10 Rezultat după elementele similare P10 = P7 + P8 − P9
P11 (P111/P112/P113) Amortizare fiscală P11 ≥ ΣP11x
P12 (P121/P122) Cheltuieli cu dobânzile deductibile P12 ≥ ΣP12x
P13 Rezerva legală deductibilă ≥ 0
P14 (P141) Provizioane fiscale P14 ≥ P141
P15 (P151) Alte sume deductibile (P151 = deducere R&D) P15 ≥ P151
P16 Total deduceri P16 = P11 + P12 + P13 + P14 + P15
P17 (P171/P172/P173) Venituri neimpozabile din dividende P17 ≥ ΣP17x
P18 Venituri din titluri de participare ≥ 0
P19 Venituri din lichidarea altei PJ ≥ 0
P20 Alte venituri neimpozabile ≥ 0
P21 Total venituri neimpozabile P21 = P17 + P18 + P19 + P20
P22 Profit / pierdere P22 = P10 − P16 − P21
P23P33 Cheltuieli nedeductibile (impozit pe profit, penalități, protocol, sponsorizare, amortizare contabilă, provizioane, art. 25(10), dobânzi reportate, aferente veniturilor neimpozabile, altele) inputs
P34 Total cheltuieli nedeductibile P34 = P23 + … + P33
P35 Profit impozabil / pierdere fiscală înainte de ajustarea cu pierderile curente P35 = P22 + P34
P36 / P37 / P38 Pierdere fiscală curentă: de reportat / transferată / primită (art. 31(2)) ≥ 0
P38a Profit impozabil / pierdere înainte de reportarea pierderilor din anii precedenți P38a = P35 + P36 + P37 − P38
P39 / P39a Pierdere fiscală de recuperat din anii precedenți / în anul curent P39a ≤ P39 (V1)
P40 Profit impozabil aferent anului P40 = P38a − P39a if > 0, else 0
P40a Pierdere fiscală aferentă anului P40a = −P38a if P38a < 0, else 0
P41 (P411/P412) Total impozit pe profit P41 = P411 + P412; P411 = 16% row, P412 = 5% (baruri/cluburi/cazinouri); P41 > 0 when P40 > 0
P42 (P421/P422P4221+P4222/P423P4231) Total credit fiscal (extern, impozit scutit, scutiri/reduceri) P42 = P421 + P422 + P423; V2–V4 cap each leg at the running tax
P43 (P431/P432) Sume sponsorizare/mecenat/burse în limită P43 ≥ P431 + P432; V5: P43 ≤ 20% · (P41 − P42)
P43a 16% pe deducerea suplimentară R&D (OUG 115/2024) ≥ 0
P44 Alte sume care se scad V6: ≤ P41 − (P42 + P43)
P45 Reducere impozit (OUG 153/2020) V7: ≤ P41 − (P42 + P43 + P44)
P46 / P47 Impozit pe profit pentru comparație / la nivelul IMCA (art. 18¹(5)) ≥ 0
P48 (P481/P482) Impozit anual datorat P48 = P481 if P46 > P47, else P482; V8; 0 for d_grup=1
P49 Impozit stabilit în urma inspecției fiscale ≥ 0
P50 Impozit declarat prin formularul 100 / reținut la sursă input — the D100 reconciliation anchor; 0 for d_grup=1
P51 Diferență urmare restituirii sponsorizării input
P52 Diferență de impozit de plată P52 = (P48 + P51) − (P49 + P50) if ≥ 0
P53 Diferență de impozit de recuperat P53 = (P49 + P50) − (P48 + P51) if ≥ 0; P52/P53 mutually exclusive

Common scenarios

Both instances validated clean (ok) against D101Validator.jar J11.0.3 on 2026-07-17, calendar-year FY2025 (Data_I="01.01.2025", Data_S="31.12.2025", deadline scadenta="250626" = 25 June 2026). The synthetic cif="1234565" is check-digit valid.

1 — Nil return (a fiscal year with no profit-tax figures; ordinary company). Only the identification block; every P* row absent; totalPlata_A="0".

<?xml version="1.0" encoding="UTF-8"?>
<declaratie101 xmlns="mfp:anaf:dgti:d101:declaratie:v10"
 d_rec="0" d_reg="0" d_anulare="0" d_succ="0" d_alte="0" d_reglem="0"
 cod_obligatie="102" luna_i="01" an_i="2025" luna="12" an="2025"
 Data_I="01.01.2025" Data_S="31.12.2025"
 scadenta="250626" cod_bug="5503010101" nr_evid="11102011225250626000037"
 totalPlata_A="0"
 nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator"
 cif="1234565" caen="6201" denumire="EXEMPLU TEST SRL"
 adresa="Mun. Bucuresti, Str. Exemplu nr. 1"/>

2 — Realistic profit-tax return (ordinary Romanian company, cod_obligatie="103"). Accounting gross result 100 000 (500 000 income − 400 000 expense), 10 000 non-deductible expenses → taxable profit 110 000, tax 16% = 17 600; 12 000 already declared via D100 during the year, so 5 600 remains to pay (P52). The nr_evid embeds cod_obligatie=103 at positions 3–5, so it differs from scenario 1. totalPlata_A="1592800" is the control sum DUK reported (rule R19; sub-rows P411/P481 and the intermediate P38a are excluded).

<?xml version="1.0" encoding="UTF-8"?>
<declaratie101 xmlns="mfp:anaf:dgti:d101:declaratie:v10"
 d_rec="0" d_reg="0" d_anulare="0" d_succ="0" d_alte="0" d_reglem="0"
 cod_obligatie="103" luna_i="01" an_i="2025" luna="12" an="2025"
 Data_I="01.01.2025" Data_S="31.12.2025"
 scadenta="250626" cod_bug="5503010101" nr_evid="11103011225250626000038"
 totalPlata_A="1592800"
 nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator"
 cif="1234565" caen="6201" denumire="EXEMPLU TEST SRL"
 adresa="Mun. Bucuresti, Str. Exemplu nr. 1"
 P1="500000" P2="400000" P3="100000"
 P7="100000" P10="100000" P22="100000"
 P33="10000" P34="10000" P35="110000"
 P38a="110000" P40="110000"
 P41="17600" P411="17600"
 P48="17600" P481="17600"
 P50="12000" P52="5600"/>

Special attention & gotchas

The pitfalls below trace either to direct wire/validator verification (the d_reglem deadline coupling, the cod_obligatie list, the scadenta formula, the nr_evid checksum, the cod_bug non-validation, the control sum, and every computation formula were each observed against D101Validator.jar J11.0.3) or to an authoritative source (OPANAF 206/2025 + the structure annex for the row meanings and legal basis; Legea 296/2023 for IMCA and the loss cap; OUG 153/2020 for the 25 June deadline). No uncorroborated practitioner claim is carried.

  • d_reglem is a checkbox, not a required 1. It flags a bank/insurer (a taxpayer whose accounting rules are issued by B.N.R. / A.S.F.): d_reglem="0" is the ordinary company, d_reglem="1" is the regulated entity — and 1 also shortens the deadline to +3 months (25 March). The verbatim technical note below (written before the structure annex was consulted) called d_reglem="1" the only accepted value; it is not — 0 is the normal case, and the nil instance above uses it.
  • cod_obligatie is NOT 101 — the jar's list is 102/103/104/105 ("valoarea '101' nu se afla in lista"). It picks the sub-type: 103 for an ordinary Romanian company, 102 for the advance-payment system, 104 for agricultural co-ops / NGOs (no D100 for 104), 105 for foreign legal persons. It also correlates with nr_evid (positions 3–5) and gates several period fields (trim_micro, Data_M, *_an_modif are null for 102).
  • d_prof is deprecated — omit it. It was a 2017 micro→profit transition flag ("nu se mai folosește"); the current mid-year micro→profit mechanism is trim_micro (the quarter the company left the micro regime), which drives the correlation between the annual D101 and the quarterly D100.
  • The deadline (and scadenta) is 25 June for FY2021–2025, not 25 March. During the OUG 153/2020 window the validator adds +6 months for reporting years 2022–2025 (and 2021-December): a calendar-year FY2025 return is due 25 June 2026 (scadenta="250626"). The +3 (25 March) term applies only to d_reglem="1" and cod_obligatie="105"; 104 is +2; a dissolution/liquidation date (Data_L/Data_B) adds one more month. scadenta is ZZLLAA and is rule-checked (R17) against Data_S, cod_obligatie, and d_reglem.
  • nr_evid is not the D300 layout — use the D101 composer, not the D300 one. D101's 23-digit number starts with 11 (not 10), carries cod_obligatie at positions 3–5, then 01, LLAA (month+year of Data_S), the 6-digit scadenta, a liquidation flag at position 18 (1 if Data_L/Data_B set, else 0), 000, and a 2-digit checksum (sum of the first 21 digits). Compose it with profit_tax_evidence_number(cod_obligatie, month, year, due_date, in_liquidation=...) (MCP: declaratie_nr_evid with form="D101") — not the D300 payment_evidence_number (prefix 10, tip_decont-keyed). DUK enforces the checksum and length but not the fixed literals, so a stale prefix-10 value with a valid checksum still passes -v; the composer emits 11 per the annex regardless.
  • cod_bug content is not validated. The jar accepts a literal cod_bug="20470101XX" (placeholder XX and all). The annex gives the two families — 2047 0101 XX and 5503 XX XX XX — but the correct budget code for the obligation is the author's responsibility; the DUK-accepted concrete value used in the instances here is 5503010101.
  • totalPlata_A is a control sum, not the tax to pay. It sums the main rows P1…P53, excluding the "din care" sub-rows (e.g. P411, P481) and the intermediate P38a — DUK reports the expected value in rule R19 ("total plata … trebuie sa fie suma …"), so set it from the error on the first pass. It may be negative. The amount actually owed is P52 (de plată) or P53 (de recuperat) — mutually exclusive.
  • IMCA (minimum turnover tax) is only for large taxpayers. Rows P46/P47 compare the profit tax against the impozit minim pe cifra de afaceri (art. 18¹, Legea 296/2023) and feed P48 (P481 profit tax vs P482 IMCA). IMCA applies only to taxpayers with prior-year turnover > €50 million; an ordinary SME leaves P46/P47/P482 blank and P48 follows P481.
  • Fiscal-loss carry-forward changed (art. 31(4¹), Legea 296/2023). Losses established from 2024 onward are recovered from taxable profit at max 70%, over the next 5 consecutive years (was 100% over 7 years). Pre-2024 losses unrecovered at 31.12.2023 continue at 70% over their remaining 7-year window; the two are cumulated for the 70% cap. This drives P39/P39a (recoverable prior-year loss) into P40.
  • Sponsorship is a tax credit, not a deduction. The sponsorship/scholarship expense is non-deductible (it rides P27 among non-deductibles) and instead reduces the tax at P43, capped by V5 at 20% · (P41 − P42) (and, in law, the lower of that and 0.75% of turnover). The unused portion carries forward up to 7 years (P432reportate din perioada precedentă).
  • Cross-form reconciliation is the real filing risk. P50 is the tax already declared for the year via formularul 100 (D100); D101 nets it at P52/P53, so the annual return must tie to the quarterly D100 filings (and trim_micro links a micro→profit transition across the two). The accounting figures P1/P2/P7 (income / expense / gross result) must equal the annual financial statements (bilanț). For d_grup=1 (fiscal-group member) the settlement rows P48/P50/P52/P53 are zeroed — the group files separately.
  • Version-alignment trap. The published XSD declares namespace …:v3 and is stale in structure; author from the v9/v10 structure annex and the validator jar. DUK's "Valoarea corecta este xmlns=…" advice is unreliable (it ping-pongs between generations) — fix the structure, not the namespace string. See the verbatim note below.

Annual return. The hardest of the common forms to author from public schemas, because there is no public schema for the live wire format. Live-proven 2026-07-17 with D101Validator.jar J11.0.3 (feed directory D101_56): a synthetic nil FY2025 return validated clean and rendered to PDF.

v10 (live wire format; NO published XSD)

  • Every XSD ANAF publishes for D101 declares namespace …:v3 — both d101_20250214.xsd and d101_20230424.xsd — while the live wire format is mfp:anaf:dgti:d101:declaratie:v10 (extracted from the smart PDF's XML-building JavaScript; the jar's newest internal validator also expects v10). The published XSDs are stale in structure too (v3 has data_i lowercase, cifs, d_succ required — v10 differs). Author from the smart-PDF template, not the XSD.
  • The jar routes period → validator generation via an internal table (d101validator/Validator.class, _dateVersionTable: 2011-01→ns v2, 2014-01→v3, … 2021-01→v9, 2024-12/2025-01→v10). When the document doesn't parse as the expected generation, DUK's "Valoarea corecta este xmlns=…" advice is garbage — it ping-pongs between v2 and v10 depending on what you declared. Do not chase it; fix the structure.
  • v10 root attributes (flat, single element declaratie101, order per the PDF template): d_rec, d_reg (0/1 — 1 means "with attached ZIP": validation passes but PDF rendering then fails with "pentru d_reg=1 trebuie atasat zip"; use 0 for a standalone return), d_anulare, d_reglem (required; only 1 was accepted2 is "outside the required interval"), cod_obligatie, luna_i/an_i (fiscal-year start), luna/an (reporting period end, 12/year for calendar-year filers), d_prof (0/1/2), capitalized date attributes Data_I/Data_S (dotted dd.mm.yyyy; v3-XSD's lowercase data_i/data_s are wrong for v10), d_alte, scadenta, cod_bug, nr_evid, totalPlata_A, declarant block, cif, caen, denumire, adresa (+ optional telefon/fax/email, representative cifR…, and the P1P83 money rows).
  • cod_obligatie is NOT 101: the jar's list is 102/103/104/105 (error: "valoarea '101' nu se afla in lista"). 102 works for a standard profit-tax return.
  • scadenta is 6 characters ZZLLAA (e.g. 250326), not a dotted date. The deadline is rule-checked against Data_S and d_reglem: with d_reglem="1" the rule demands month+3 (25.03 of the following year); when d_reglem is absent the historic rule (FY2022–2025) demanded month+6 (25.06). Mismatches produce rule R17 with the expected formula.
  • nr_evid — the D300/D100 23-digit layout with prefix 11, cod_obligatie in the code slot, and the payment due date matching scadenta: 11 102 01 1225 250326 0000 34, as profit_tax_evidence_number composes it. (A stale prefix-10 value, 10102011225250326000033, was also validated — DUK checks only length + checksum, not the fixed literals; see the pitfalls above. The annex prefix is 11.)
  • Minimal valid instance (nil FY2025 calendar-year return):
<?xml version="1.0"?>
<declaratie101 d_rec="0" d_reg="0" d_anulare="0" d_reglem="1"
 cod_obligatie="102" luna_i="01" an_i="2025" luna="12" an="2025"
 d_prof="0"
 Data_I="01.01.2025" Data_S="31.12.2025" d_alte="0"
 scadenta="250326"
 cod_bug="20470101XX" nr_evid="11102011225250326000034"
 totalPlata_A="0"
 nume_declar="Popescu" prenume_declar="Ion" functie_declar="Administrator"
 cif="1234565" caen="6201" denumire="EXEMPLU TEST SRL"
 adresa="Mun. Bucuresti, Str. Exemplu nr. 1"
 xmlns="mfp:anaf:dgti:d101:declaratie:v10"/>

Recovering an undocumented wire format (method note)

The pattern that worked here generalizes to any form whose published XSD is stale: (1) download the current smart PDF; (2) decompress its streams and find the xml+= JavaScript that assembles the document — it is the authoritative attribute list, order, formats, and namespace; (3) let DUK's rule errors supply the value-level constraints (code lists, deadline formulas); (4) the jar's parameters/Parameters_v*.class constant pool holds the nomenclature tables (obligation codes ↔ budget codes).