ANAF compliance · Interop · CII / Factur-X

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.

An invoice goes in one format, comes out in anotherPOST · in memory · zero retention
POST /interop/v1/ubl-to-cii
// 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…"
} }
What you get One POST endpoint, one invoice, one response. The CII → UBL conversion goes through the same issuing engine as e-Invoice, so the result follows the CIUS-RO rules. We do not build Factur-X PDFs — we only unpack the XML from them.
Formats
CIUS-RO UBL 2.1 ⇄ UN/CEFACT CII
Core
EN16931 (the shared semantics)
PDF
Factur-X · ZUGFeRD · XRechnung
Operations
ubl-to-cii · cii-to-ubl · facturx-extract
Retention
none
01 The problem

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.

A

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.

B

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.

C

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.

D

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.

E

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.

F

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.

None of this sets you apartWriting and maintaining a UBL↔CII converter, plus an XML extractor for Factur-X PDFs, is work nobody congratulates you for — and that costs you at every schema change. It is exactly the layer we move onto our side, so you call an endpoint and move on.
02 What it does

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.

POST /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.

POST /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.

POST /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.

03 Zero retention

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.

01

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.

02

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.

03

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.

04

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.

Why it matters to youAn invoice holds parties, amounts and tax codes — data that makes any service storing it a target and a liability. We chose the version where there is nothing to steal: a stateless tool that converts and unpacks and does not remember.
04 Faithful conversion

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.

05 What we cover

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.

CIUS-RO (UBL 2.1) UN/CEFACT CII EN16931 core Invoice CreditNote Factur-X ZUGFeRD XRechnung Seller / Buyer Lines + VAT Totals by category Payment means FlateDecode (PDF) Format detection

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.

06 Integration

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.

POST/api/anaf/v1/interop/cii-to-ublapplication/json
# 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": […] }
} }
When the body is wrong

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
} }
07 Questions

Before the first conversion.

The rest, in the frequently asked questions and in the documentation.

The result goes through the same issuing engine as the e-Invoice product, so it follows the CIUS-RO rules (derived VAT categories, calculated totals, code lists). We do not guarantee validity for any incoming CII, though — it depends on how complete the source is. For the official verdict, run the result through e-Invoice /validate. Some information can be lost in conversion, but the core — number, parties, lines, totals, VAT — is preserved.

The first conversion takes as long as reading this page. One token, one invoice, the converted format back. Zero retention, from the first call.
Generate a token All modules