Build a RO e-Factura UBL 2.1 Invoice into CIUS-RO XML
Skill: Convert invoice data into a CIUS-RO UBL 2.1 Invoice for ANAF RO e-Factura
Region: Romania (România)
Category: E-invoicing — RO e-Factura (ANAF SPV / Sistemul Național RO e-Factura)
Does: Takes invoice data (header, parties, lines, VAT) and produces an EN 16931 UBL 2.1 Invoice conforming to the CIUS-RO national rules, ready to upload to the ANAF SPV (Spațiul Privat Virtual) RO e-Factura endpoint.
Standard: EN 16931 (semantic) + OASIS UBL 2.1 (syntax) + CIUS-RO customization (urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1)
This XML is the invoice payload uploaded to ANAF SPV via the RO e-Factura
uploadAPI; ANAF returns an index (index_incarcare), validates, and issues a sealed response (mesaj) with a download id. The AI produces the UBL; the user validates against ANAF's CIUS-RO validators and submits. Issuers must transmit within 5 calendar days of the invoice issue date (for B2B and B2G; B2C is in scope from 2025). Verify current CIUS-RO version and TVA rates before use.
When this applies
- A Romanian-established taxable person issuing a B2B, B2G, or (from 2025) B2C invoice that must travel through the national RO e-Factura system.
- The output is a single UBL 2.1
Invoice(orCreditNotefor corrections) carrying the CIUS-ROCustomizationID. - Excluded: simplified receipts handled only via the e-bonuri / SAF-T flows, and exports outside the RO e-Factura mandate — confirm scope before generating.
Conversion procedure
- Read the source. Accept a PDF text layer (
pdftotext), CSV/JSON line export, or pasted invoice text. Parse seller, buyer, invoice metadata, and every line. - Extract fields. Identify: seller name, CUI/CIF (and RO VAT prefix if VAT-registered), seller address + county; buyer name, CUI/CNP, address + county; invoice number, issue date, due date, currency, document type; per line description, quantity, unit, net unit price, VAT category + rate; document-level allowances/charges. If a required field (e.g. buyer CUI for a B2B invoice) is missing, stop and ask — do not invent identifiers.
- Normalize. Dates →
YYYY-MM-DD. CUI → strip spaces/dots; for a VAT-registered party setcbc:CompanyIDtoRO+ digits (e.g.RO12345678); the legal registration id goes incac:PartyLegalEntity/cbc:CompanyID. County → ISORO-XXcode (Bucharest =RO-B). Amounts → dot decimal, 2 decimals, no thousands separator. - Compute. Recompute line
LineExtensionAmount, eachTaxSubtotal(TaxableAmount,TaxAmount),TaxExclusiveAmount,TaxInclusiveAmount,PayableAmount. Never copy a printed total blindly; flag mismatches. - Emit the UBL. Build the
Invoiceper the Document structure section, using the worked example as the template. SetCustomizationIDandProfileIDexactly. - Validate. Work through the Validation checklist; run the file through the ANAF CIUS-RO validator before upload.
Source → UBL field map
| From the source | → Target element / field |
|---|---|
| CIUS-RO customization (fixed) | cbc:CustomizationID |
| Process profile (fixed) | cbc:ProfileID (urn:fdc:peppol.eu:2017:poacc:billing:01:1.0) |
| Invoice number | cbc:ID |
| Issue date → YYYY-MM-DD | cbc:IssueDate |
| Due date → YYYY-MM-DD | cbc:DueDate |
| Invoice type code | cbc:InvoiceTypeCode (380 invoice, 381 credit note) |
| Currency | cbc:DocumentCurrencyCode |
| Seller name | cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name |
| Seller VAT id (RO prefix) | cac:AccountingSupplierParty/.../cac:PartyTaxScheme/cbc:CompanyID |
| Seller legal reg id (CUI) | cac:AccountingSupplierParty/.../cac:PartyLegalEntity/cbc:CompanyID |
| Seller street / city | cac:PostalAddress/cbc:StreetName, cbc:CityName |
| Seller county (ISO) | cac:PostalAddress/cbc:CountrySubentityCode (RO-B, RO-CJ, …) |
| Seller country | cac:PostalAddress/cac:Country/cbc:IdentificationCode (RO) |
| Buyer name | cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name |
| Buyer VAT id / legal id | cac:AccountingCustomerParty/.../cac:PartyTaxScheme/cbc:CompanyID, cac:PartyLegalEntity/cbc:CompanyID |
| Buyer county (ISO) | cac:AccountingCustomerParty/.../cbc:CountrySubentityCode |
| Line id / number | cac:InvoiceLine/cbc:ID |
| Line quantity + unit | cac:InvoiceLine/cbc:InvoicedQuantity (@unitCode) |
| Line net amount | cac:InvoiceLine/cbc:LineExtensionAmount |
| Line description | cac:InvoiceLine/cac:Item/cbc:Name |
| Line VAT category + rate | cac:InvoiceLine/cac:Item/cac:ClassifiedTaxCategory/cbc:ID, cbc:Percent |
| Line net unit price | cac:InvoiceLine/cac:Price/cbc:PriceAmount |
| VAT per category | cac:TaxTotal/cac:TaxSubtotal (cbc:TaxableAmount, cbc:TaxAmount) |
| Total VAT | cac:TaxTotal/cbc:TaxAmount |
| Net total | cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount |
| Gross total | cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount |
| Amount due | cac:LegalMonetaryTotal/cbc:PayableAmount |
Repeat cac:InvoiceLine once per line and cac:TaxSubtotal once per VAT category/rate.
Document structure
Invoice (xmlns urn:oasis:names:specification:ubl:schema:xsd:Invoice-2)
├── cbc:CustomizationID (CIUS-RO 1.0.1)
├── cbc:ProfileID
├── cbc:ID (invoice number)
├── cbc:IssueDate
├── cbc:DueDate (optional)
├── cbc:InvoiceTypeCode (380 / 381 / 384 / 389)
├── cbc:DocumentCurrencyCode (RON / EUR …)
├── cac:AccountingSupplierParty
│ └── cac:Party
│ ├── cac:PostalAddress (StreetName, CityName, CountrySubentityCode RO-XX, Country RO)
│ ├── cac:PartyTaxScheme (CompanyID = RO+digits, TaxScheme/ID = VAT)
│ ├── cac:PartyLegalEntity (RegistrationName, CompanyID = CUI)
│ └── cac:PartyName / cac:Contact
├── cac:AccountingCustomerParty
│ └── cac:Party (same shape as supplier)
├── cac:PaymentMeans (optional — PaymentMeansCode, PayeeFinancialAccount/IBAN)
├── cac:TaxTotal
│ ├── cbc:TaxAmount (total VAT, document currency)
│ └── cac:TaxSubtotal (1..n) (TaxableAmount, TaxAmount, TaxCategory ID+Percent)
├── cac:LegalMonetaryTotal
│ ├── cbc:LineExtensionAmount
│ ├── cbc:TaxExclusiveAmount
│ ├── cbc:TaxInclusiveAmount
│ ├── cbc:AllowanceTotalAmount (optional)
│ └── cbc:PayableAmount
└── cac:InvoiceLine (1..n)
├── cbc:ID
├── cbc:InvoicedQuantity @unitCode
├── cbc:LineExtensionAmount
├── cac:Item (Name, ClassifiedTaxCategory ID+Percent+TaxScheme VAT)
└── cac:Price (PriceAmount)
All three top-level namespaces (Invoice-2, cac, cbc) are mandatory. cac:PartyTaxScheme is required only for a VAT-registered party; cac:PaymentMeans is optional.
Code tables
cbc:InvoiceTypeCode (UNTDID 1001, CIUS-RO subset)
| Code | Meaning |
|---|---|
380 |
Commercial invoice (factură) |
381 |
Credit note (factură storno) |
384 |
Corrected invoice |
389 |
Self-billed invoice |
751 |
Invoice information for accounting purposes |
VAT category cac:ClassifiedTaxCategory/cbc:ID (UNCL5305) + Romanian rate
| Category | Percent | Meaning |
|---|---|---|
S |
19 |
Standard rate (cota standard) |
S |
9 |
Reduced rate (food, medicine, water, hotels) |
S |
5 |
Reduced rate (books, social housing, certain supplies) |
Z |
0 |
Zero-rated |
E |
0 |
Exempt without credit (scutit fără drept de deducere) |
AE |
0 |
Reverse charge (taxare inversă) |
K |
0 |
Intra-Community supply (exempt, art. 294) |
G |
0 |
Export outside EU (exempt) |
O |
— | Outside scope of VAT |
Romanian county codes cbc:CountrySubentityCode (ISO 3166-2:RO, selected)
| Code | County |
|---|---|
RO-B |
București (Bucharest) |
RO-CJ |
Cluj |
RO-IS |
Iași |
RO-TM |
Timiș |
RO-BV |
Brașov |
RO-CT |
Constanța |
RO-IF |
Ilfov |
RO-DJ |
Dolj |
cac:PaymentMeans/cbc:PaymentMeansCode (UNTDID 4461, selected)
| Code | Meaning |
|---|---|
30 |
Credit transfer |
31 |
Debit transfer |
42 |
Payment to bank account |
48 |
Bank card |
10 |
Cash (numerar) |
Calculation rules
- Line net (
LineExtensionAmount) =InvoicedQuantity×Price/PriceAmount(less any line allowance), rounded to 2 decimals. - TaxSubtotal/TaxableAmount = Σ of line
LineExtensionAmountfor that VAT category + rate (minus document allowances for that category). - TaxSubtotal/TaxAmount =
TaxableAmount×Percent÷ 100, rounded to 2 decimals. - TaxTotal/TaxAmount = Σ of all
TaxSubtotal/TaxAmount. - LineExtensionAmount (LegalMonetaryTotal) = Σ line nets. TaxExclusiveAmount = LineExtensionAmount − document allowances + document charges.
- TaxInclusiveAmount =
TaxExclusiveAmount+TaxTotal/TaxAmount. PayableAmount =TaxInclusiveAmount− prepaid amount + rounding. - CIUS-RO rule BR-CO-15:
TaxInclusiveAmount=TaxExclusiveAmount+ total VAT. Rule BR-RO-A050x: everyScategory line must carry a valid Romanian rate (19,9,5). - Amounts use dot decimal, 2 decimals;
@currencyIDon amount elements must equalDocumentCurrencyCode. Always recompute; flag any mismatch with the source.
Worked example (end-to-end)
Input — pasted invoice
Furnizor: Exemplu Distributie SRL, CUI RO12345678, J40/1234/2018
Adresa: Str. Victoriei 10, Bucuresti, sector 1
Client: Client Beta SRL, CUI RO87654321
Adresa: Calea Mosilor 5, Cluj-Napoca, jud. Cluj
Factura nr. EX-2026-000045, data 2026-06-10, scadenta 2026-07-10, moneda RON
Linia 1: Servicii de consultanta, 10 ore x 200,00 = 2.000,00, TVA 19%
Total fara TVA: 2.000,00 TVA: 380,00 Total: 2.380,00
After extraction + normalization (intermediate)
{
"id": "EX-2026-000045",
"issueDate": "2026-06-10",
"dueDate": "2026-07-10",
"typeCode": "380",
"currency": "RON",
"seller": { "name": "Exemplu Distributie SRL", "vat": "RO12345678", "cui": "12345678",
"street": "Str. Victoriei 10", "city": "Bucuresti", "county": "RO-B" },
"buyer": { "name": "Client Beta SRL", "vat": "RO87654321", "cui": "87654321",
"street": "Calea Mosilor 5", "city": "Cluj-Napoca", "county": "RO-CJ" },
"lines": [ { "id": "1", "desc": "Servicii de consultanta", "qty": 10, "unit": "HUR",
"unitPrice": 200.00, "net": 2000.00, "cat": "S", "rate": 19 } ],
"taxableByRate": { "19": { "base": 2000.00, "vat": 380.00 } },
"lineTotal": 2000.00, "taxExclusive": 2000.00, "taxInclusive": 2380.00, "payable": 2380.00
}
Output — CIUS-RO UBL 2.1 Invoice
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>EX-2026-000045</cbc:ID>
<cbc:IssueDate>2026-06-10</cbc:IssueDate>
<cbc:DueDate>2026-07-10</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Str. Victoriei 10</cbc:StreetName>
<cbc:CityName>Bucuresti</cbc:CityName>
<cbc:CountrySubentityCode>RO-B</cbc:CountrySubentityCode>
<cac:Country>
<cbc:IdentificationCode>RO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>RO12345678</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Exemplu Distributie SRL</cbc:RegistrationName>
<cbc:CompanyID>12345678</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Calea Mosilor 5</cbc:StreetName>
<cbc:CityName>Cluj-Napoca</cbc:CityName>
<cbc:CountrySubentityCode>RO-CJ</cbc:CountrySubentityCode>
<cac:Country>
<cbc:IdentificationCode>RO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>RO87654321</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Client Beta SRL</cbc:RegistrationName>
<cbc:CompanyID>87654321</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="RON">380.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="RON">2000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="RON">380.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="RON">2000.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="RON">2000.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="RON">2380.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="RON">2380.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="RON">2000.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Servicii de consultanta</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="RON">200.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
Normalisations shown: RO12345678 kept on PartyTaxScheme/CompanyID, bare 12345678 on PartyLegalEntity/CompanyID; county Bucuresti, sector 1 → RO-B, jud. Cluj → RO-CJ; amounts 2.000,00 → 2000.00; line net recomputed 10 × 200.00 = 2000.00; VAT recomputed 2000.00 × 19% = 380.00; TaxInclusiveAmount = 2000.00 + 380.00 = 2380.00. This payload is uploaded to ANAF SPV (/upload with standard=UBL), which returns index_incarcare and, after validation, a sealed mesaj downloadable by id.
Validation checklist
- All required fields extracted; AI asked about anything missing or ambiguous (no invented CUI/CIF, dates, or amounts)
-
cbc:CustomizationID= CIUS-RO1.0.1;cbc:ProfileIDset; three UBL namespaces declared -
cbc:InvoiceTypeCodevalid (380/381/384/389);DocumentCurrencyCodeset - VAT-registered parties:
RO+digits onPartyTaxScheme/CompanyID, CUI onPartyLegalEntity/CompanyID -
cbc:CountrySubentityCodeis a validRO-XXISO code (Bucharest =RO-B);Country/IdentificationCode=RO - One
cac:InvoiceLineper line; eachItem/ClassifiedTaxCategorycarries categoryID+Percent - One
cac:TaxSubtotalper VAT category/rate;TaxAmount=TaxableAmount×Percent÷ 100 (2dp) -
TaxInclusiveAmount=TaxExclusiveAmount+ total VAT (BR-CO-15);PayableAmountcorrect -
@currencyIDon every amount equalsDocumentCurrencyCode; amounts dot-decimal 2dp - Recomputed totals match the source or discrepancy flagged
- File passes the ANAF CIUS-RO validator and is uploaded within 5 calendar days of issue
Last updated: 2026-06-13 — verify the active CIUS-RO version, Romanian TVA rates, county codes, and ANAF RO e-Factura upload API before use.