The same invoice, in any European format.
You convert invoices between CIUS-RO e-Invoice (UBL 2.1) and UN/CEFACT CII, and extract the XML from a Factur-X or ZUGFeRD PDF — all through one API, without storing anything.
CIUS-RO is the UBL dialect ANAF requires; CII is the format used in France (Factur-X), Germany (ZUGFeRD) and across many EU B2B exchanges. Both start from the same EN16931 core. We translate between them and pull the invoice out of the PDF — in memory, with zero retention.
// body: a CIUS-RO (UBL) invoice
// → { data: { standard: "CII",
// guideline: "urn:cen.eu:en16931:2017", xml: "<rsm:CrossIndustryInvoice…" } }
POST /interop/v1/facturx-extract // body: a Factur-X PDF
{ "data": {
"format_detectat": "CII",
"xml": "<?xml version=\"1.0\"?><rsm:CrossIndustryInvoice…"
} }
- Formats
- CIUS-RO UBL 2.1 ⇄ UN/CEFACT CII
- Core
- EN16931 (the shared semantics)
- Factur-X · ZUGFeRD · XRechnung
- Operations
- ubl-to-cii · cii-to-ubl · facturx-extract
- Retention
- none
The same invoice, two format worlds that do not speak to each other.
Between the e-Invoice ANAF requires and the invoice a European partner expects sits a format translation — the same semantics, different syntaxes — that someone has to get right.
UBL vs CII
CIUS-RO is UBL 2.1 (Invoice / CreditNote root). CII is UN/CEFACT (CrossIndustryInvoice root). The same fields, different element names and a different order — strict in both.
Factur-X / ZUGFeRD
In France and Germany the invoice travels as a PDF with the invoice XML embedded (PDF/A-3). To process it as structured data you first have to pull the XML out of the PDF.
Element order
The sequence in the CII schema is strict: one element in the wrong place and the file is rejected. The UBL↔CII mapping is not a simple rename, it is a rewrite in the correct order.
Totals and VAT
Bases, rates and VAT categories have to come out faithfully on both sides. One rounding moved and the totals no longer close.
A shared core, different wrappers
Both derive from EN16931 — the same base semantics. The difference is syntactic, exactly the kind of repetitive, low-value work that lends itself to automation.
It is not your product
Your customer does not pay you because you know the ram:ApplicableHeaderTradeSettlement sequence by heart. They pay you for your product. Format translation is pure cost.
Three operations. One translation each way and one unpack.
Each is an independent POST call. You use the one you need — conversion one way, the other way, or extraction from a PDF.
/ubl-to-cii
UBL → CII
You send a CIUS-RO invoice (UBL 2.1) and get the UN/CEFACT CII equivalent, on the EN16931 core — parties, lines, VAT and totals mapped into the correct CII schema sequence. For when you send to a European partner.
/cii-to-ubl
CII → UBL
You send a CII invoice and get a valid CIUS-RO e-Invoice. The conversion goes through the same issuing engine as the e-Invoice product, so it inherits the VAT category derivation, the calculated totals and the code lists.
/facturx-extract
Extract from Factur-X
You send the bytes of a Factur-X / ZUGFeRD / XRechnung PDF and get the embedded invoice XML, plus the detected format (CII or UBL). A first step before validation or conversion.
Your invoice passes through the conversion, not through our archive.
This is the answer to “why would I send my invoice to a third party to convert it”. Because, in practice, you leave it nowhere — we convert and forget.
Processed in memory
The XML and the PDF are never written to disk. They arrive in the request, are converted or unpacked in memory and are gone when the response leaves. There is no invoice of yours at our end.
Local conversion
The format translation and the extraction from the PDF run on our side, on the server holding your response. We do not send the invoice to an external conversion service.
Logs without content
What we keep is a result code and a duration — that is all. The invoice number, the parties, the amounts go into no log, neither ours nor an observability service’s.
No SPV
We file nothing on your behalf and we do not connect to SPV. We convert the format; what you do with the result — file it, send it, archive it — stays with you, using your own credentials.
We do not just move labels around. We keep the meaning.
The mapping starts from the EN16931 core shared by both formats, and the amounts are taken from the source — with no recalculation to introduce drift.
The EN16931 core
Number, dates, document type, parties (seller/buyer with address, tax code, VAT number), lines and totals by VAT category — the base semantics both formats share, mapped field by field.
The correct schema sequence
On UBL → CII we emit the elements in exactly the order the CII schema requires (ExchangedDocument, then the lines, then the agreement, the delivery and the settlement). A file in order, not just one with translated names.
Amounts from the source
On UBL → CII, line nets, subtotals and totals are read straight from the source UBL, where they are authoritative. On CII → UBL, the totals are recalculated by the e-Invoice issuing engine from the lines received.
CIUS-RO guaranteed on the way back
The CII → UBL conversion does not write UBL “by hand”: it goes through the e-Invoice engine, so the result follows the CIUS-RO rules. For the full verdict, run the result through e-Invoice /validate.
The formats that matter in the EU, plus the PDF.
The invoice core of each format, mapped both ways, plus extraction from the three usual PDF wrappers.
We cover the EN16931 invoice core in both formats, plus extraction from Factur-X / ZUGFeRD / XRechnung. If you hit a field or a profile we do not handle correctly, write to us — real cases take priority in what we build.
An invoice goes in one format. It comes out in the other.
You send the XML (raw or base64) and get the converted XML. No mandatory SDK — the HTTP client you already have.
# cii-to-ubl: a CII invoice → a valid CIUS-RO e-Invoice (via the e-Invoice engine)
curl "https://oneapi.ro/api/anaf/v1/interop/cii-to-ubl" \
-H "Authorization: Bearer $ONEAPI_TOKEN" \
-H "Content-Type: application/xml" \
--data-binary @factura-cii.xml
# → 200 OK
{ "data": {
"standard": "CIUS-RO",
"xml": "<Invoice xmlns=…>…</Invoice>",
"meta": { "totals": {…}, "vat_breakdown": […] }
} }
Code, message and the field involved
If you send something other than the expected format — a UBL to the CII endpoint, a PDF with no embedded XML — you get a 422 with a stable code (for example factura_x_fara_xml), a message and, where relevant, the field involved. Enough to fix it first time.
HTTP/1.1 422 Unprocessable Content
{ "eroare": {
"cod": "factura_x_fara_xml",
"mesaj": "PDF-ul nu conține un XML de factură încorporat.",
"camp": null,
"request_id": null
} }
Before the first conversion.
The rest, in the frequently asked questions and in the documentation.