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).
Request body
The request body is the whole document, sent raw (Content-Type: application/xml) — not an object with fields.
Query parameters
minimum, basicwl, basic, en16931 (default), extended.
e.g. basic
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-datawith thefisierfield (curl -F fisier=@document.xml) instead of a raw body. - Takes an invoice in UBL CIUS-RO (
Invoice/CreditNoteroot) 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/renderproduces — 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. - ⚠️
profilis 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,basicis the more cautious one. - The normal response is a raw PDF, with the profile and attachment name in the
X-Facturx-ProfilandX-Facturx-Atasamentheaders. With?format=base64you 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.
Factur-X 1.0 / PDF/A-3B.
CIUS-RO or CII.
EN 16931).
factur-x.xml, fixed by the specification: a conforming reader looks for exactly that name.
?format=base64).
Response examples
body: @efactura.xml
The response is a binary document, not JSON: application/pdf, 54,3 KB in this example.
body: @efactura.xml
The response is a binary document, not JSON: application/pdf, 54,3 KB in this example.
body: @efactura-stornare.xml
The response is a binary document, not JSON: application/pdf, 53,9 KB in this example.
Error codes
| Code | Slug | When it occurs |
|---|---|---|
| 401 | neautentificat | Token missing, invalid, expired or revoked. |
| 403 | feature_indisponibil | The current plan does not include the feature the route depends on. |
| 422 | xml_invalid | The body is neither UBL (Invoice/CreditNote) nor CII (CrossIndustryInvoice), the XML is invalid, or profil is unknown. |
| 429 | cota_depasita | The 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"
}
}