oneapi
Sign in
Anaf v1 / Interop (CII / Factur-X)

Invoice → Factur-X PDF

Body = XML (brut sau base64), UBL CIUS-RO sau CII — se recunoaşte după rădăcină. Întoarce PDF brut;
cu ?format=base64, un envelope {data, meta} cu PDF-ul codat, pentru clienţii care nu pot citi
binar. ?profil= alege nivelul declarat în metadate (implicit en16931).

POST
https://oneapi.ro/api/anaf/v1/interop/facturx-build

Request body

The request body is the whole document, sent raw (Content-Type: application/xml) — not an object with fields.

From a UBL invoice

efactura.xml application/xml · 4,0 KB — sent as is, in the request body.

BASIC profile

efactura.xml application/xml · 4,0 KB — sent as is, in the request body.

From a credit note

efactura-stornare.xml application/xml · 3,6 KB — sent as is, in the request body.

Query parameters

NameTypeDescriptionAccepted values
profiloptional text The level declared in the metadata: minimum, basicwl, basic, en16931 (default), extended. e.g. basic
formatoptional text Absent = raw PDF. base64 = {data, meta} envelope with the PDF encoded. e.g. base64

How it behaves

  • The document can also be sent as a file: multipart/form-data with the fisier field (curl -F fisier=@document.xml) instead of a raw body.
  • Takes an invoice in UBL CIUS-RO (Invoice/CreditNote root) or in CII (CrossIndustryInvoice) — it detects which — and returns a Factur-X PDF: the human-readable layout AND the invoice XML in one file. This is the form France (Factur-X) and Germany (ZUGFeRD) require, and it is spreading across European B2B.
  • ⚠️ Factur-X embeds CII, not UBL — they are not interchangeable. Send UBL and we convert it for embedding; send CII and we keep it EXACTLY as given (a round trip could drop fields that have no UBL counterpart) and convert only a copy for the layout.
  • The layout is the same one /efactura/render produces — the same template, deliberately: two layouts would mean two invoices that look different for the same document, and the one inside Factur-X is what the end customer sees.
  • ⚠️ profil is what we DECLARE in the metadata, not what we verified. Verifying a Factur-X profile requires its Schematron, which we do not have. We validate the structure (the official CII D16B XSD, during conversion); matching the profile remains your claim. If unsure, basic is the more cautious one.
  • The normal response is a raw PDF, with the profile and attachment name in the X-Facturx-Profil and X-Facturx-Atasament headers. With ?format=base64 you get the usual {data, meta} envelope, for clients that cannot read binary.
  • Zero retention. Neither the XML received nor the PDF produced touches disk: embedding happens from memory, and the renderer's working files live in /dev/shm (RAM). Nothing is logged.

What it is for

  • Sending a Romanian invoice to a French or German partner who expects Factur-X/ZUGFeRD.
  • One file that both the person in accounting and the system importing it can read, instead of two attachments.
  • Archiving: PDF/A-3 is a long-term archival format, with the structured data inside it.

Response structure

All fields below live inside data.

FieldTypeDescription
standard What was produced: Factur-X 1.0 / PDF/A-3B.
intrare The format detected in the body: CIUS-RO or CII.
profil The profile written into the metadata, in the form the specification requires (e.g. EN 16931).
atasament The embedded file name — always factur-x.xml, fixed by the specification: a conforming reader looks for exactly that name.
pdf The PDF, base64-encoded (only with ?format=base64).

Response examples

body: @efactura.xml

POSThttps://oneapi.ro/api/anaf/v1/interop/facturx-build
The response is a binary document, not JSON: application/pdf, 54,3 KB in this example.

Download the document this example returns

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
422xml_invalidThe body is neither UBL (Invoice/CreditNote) nor CII (CrossIndustryInvoice), the XML is invalid, or profil is unknown.
429cota_depasitaThe plan's monthly quota has been exceeded (see Retry-After).

Errors in the Anaf module use the same envelope as the rest of the platform, with two extra fields: {eroare: {cod, mesaj, camp, request_id}}. eroare.cod is stable and is what you branch on; on validation (422) the code is case-specific: xml_invalid, xml_nu_e_factura, unitate_necunoscuta, luna_invalida and so on. camp points at the offending field when one can be identified.

{
    "eroare": {
        "cod": "xml_invalid",
        "mesaj": "The body is neither UBL (Invoice/CreditNote) nor CII (CrossIndustryInvoice), the XML is invalid, or profil is unknown.",
        "camp": "profil",
        "request_id": "0199c1f0-6e1a-7c3d-9b2f-4a8e5d1c7b04"
    }
}