# Factur-X & ZUGFeRD E-Invoice Generator + Validator (`josefbednar/factur-x-zugferd-e-invoice`) Actor

Generate compliant Factur-X / ZUGFeRD e-invoices (PDF/A-3 with embedded EN 16931 XML) from simple JSON, and validate or extract existing e-invoice PDFs & XML including XRechnung. Schematron-checked, UBL export. Ready for the France & Germany B2B e-invoicing mandates.

- **URL**: https://apify.com/josefbednar/factur-x-zugferd-e-invoice.md
- **Developed by:** [Josef Bednář](https://apify.com/josefbednar) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 invoice generateds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Factur-X & ZUGFeRD E-Invoice Generator + Validator

Generate **legally compliant hybrid e-invoices** — a normal, human-readable PDF with the
machine-readable **EN 16931 XML embedded inside** (PDF/A-3) — from a simple JSON object.
Or point the actor at an existing e-invoice (PDF or XML) and get a **full compliance
validation report**. Also extracts embedded XML and converts to **UBL 2.1** and
**XRechnung**.

**Why now:** France mandates B2B e-invoicing (Factur-X) starting **September 2026**, with
all companies required to *receive* e-invoices from day one. Germany's ZUGFeRD/XRechnung
mandate is already phasing in since January 2025. Every ERP, SaaS, and agency that bills
French or German companies needs to produce and check these formats — this actor does it
in one API call, with no Java stack, no schematron setup, no PDF/A tooling to maintain.

### What it does

| Mode | In | Out |
|---|---|---|
| **generate** | Invoice as JSON (or JSON + your branded PDF) | Factur-X/ZUGFeRD PDF (PDF/A-3), standalone CII XML, optional UBL 2.1, validation report |
| **validate** | Any e-invoice PDF or XML (URL / base64 / pasted XML) | Valid/invalid + detected profile + every rule violation with rule IDs (BR-…, BR-CO-…, BR-DE-…) |
| **extract** | Factur-X/ZUGFeRD PDF | The embedded XML + quick summary (number, total, currency, guideline) |

- **Profiles:** EN 16931 (Comfort — the one both mandates accept), Basic, Extended, and
  **XRechnung 3.0** (German federal, XML-only)
- **Keep your branding:** pass your own invoice PDF (`basePdf`) — it is converted to
  PDF/A-3 and the XML is embedded into it. Without it, a clean standardized invoice PDF
  is rendered from your data (English, German, or French labels)
- **Totals done right:** line totals, VAT breakdown per rate/category, and grand totals
  are computed by the actor, so the EN 16931 arithmetic rules (BR-CO-\*) always hold
- **Pre-validated:** every generated invoice is run through full XSD + Schematron
  validation by default and ships with its report
- **VAT scenarios:** standard (S), zero-rated (Z), exempt (E), **reverse charge (AE)**,
  intra-Community supply (K), export (G) — with sensible default exemption reasons
- Validation engine: [Mustangproject](https://www.mustangproject.org/) — the
  open-source reference implementation used across the industry

### Generate — minimal example

```json
{
  "mode": "generate",
  "invoice": {
    "number": "INV-2026-0042",
    "issueDate": "2026-08-08",
    "dueDate": "2026-09-07",
    "currency": "EUR",
    "seller": {
      "name": "Atelier Lumière SARL",
      "street": "12 Rue de la Paix", "city": "Paris", "zip": "75002",
      "countryCode": "FR", "vatId": "FR40303265045"
    },
    "buyer": {
      "name": "Bau & Technik GmbH",
      "street": "Torstrasse 1", "city": "Berlin", "zip": "10115",
      "countryCode": "DE", "vatId": "DE123456789"
    },
    "payment": { "iban": "FR7630006000011234567890189", "terms": "Payable within 30 days." },
    "lines": [
      { "name": "UX design sprint", "quantity": 3, "unitCode": "DAY", "unitPrice": 850, "vatRate": 20 },
      { "name": "Design system licence", "quantity": 1, "unitPrice": 490, "vatRate": 20 }
    ]
  }
}
```

Result (dataset record):

```json
{
  "status": "SUCCESS",
  "mode": "generate",
  "profile": "en16931",
  "invoiceNumber": "INV-2026-0042",
  "totals": { "net": 3040, "tax": 608, "gross": 3648, "due": 3648 },
  "pdfUrl": "https://api.apify.com/v2/key-value-stores/…/records/invoice.pdf",
  "xmlUrl": "https://api.apify.com/v2/key-value-stores/…/records/factur-x.xml",
  "validation": { "valid": true, "errorCount": 0, "reportUrl": "…" }
}
```

Line fields: `name` (required), `quantity` (required), `unitPrice` (net, required),
`vatRate` (%), `unitCode` (UN/ECE rec 20 — `C62` unit, `H87` piece, `HUR` hour, `DAY`,
`KGM`…), `vatCategory` (`S` default, `Z`, `E`, `AE`, `K`, `G`), `description`.

Invoice extras: `buyerReference` (required for XRechnung), `orderReference`,
`deliveryDate`, `note`, `paidAmount`, `typeCode` (`380` invoice, `381` credit note),
seller/buyer `registrationId` (SIRET/HRB/IČO), `taxId`, `electronicAddress`,
`contactName` / `contactEmail` / `contactPhone`.

### Validate — example

```json
{ "mode": "validate", "file": "https://example.com/incoming-invoice.pdf" }
```

```json
{
  "status": "SUCCESS", "valid": false, "fileType": "pdf",
  "profile": "urn:cen.eu:en16931:2017",
  "errorCount": 1, "warningCount": 0,
  "messages": [
    { "severity": "error", "ruleId": "BR-CO-25",
      "message": "[BR-CO-25]-In case the Amount due for payment (BT-115) is positive, either the Payment due date (BT-9) or the Payment terms (BT-20) shall be present." }
  ],
  "reportUrl": "…/validation-report.xml"
}
```

Accepts Factur-X / ZUGFeRD PDFs (any version), CII XML, UBL XML, and XRechnung — the
format and profile are auto-detected. The full validator report (XML) is stored alongside.

### Use it from your stack

- **API:** `POST https://api.apify.com/v2/acts/josefbednar~factur-x-zugferd-e-invoice/run-sync-get-dataset-items?token=…` with the JSON input — one HTTP call, response contains the URLs
- **AI agents / MCP:** works as an MCP tool out of the box on Apify — let your agent
  produce compliant invoices or triage incoming ones
- **Zapier / Make / n8n:** use the Apify integration, map your order data into `invoice`

### Notes & limits

- Amounts are treated as **net**; document-level allowances/charges are not yet supported
  (per-line pricing covers the common cases — tell us in Issues if you need BG-20/BG-21)
- `basePdf` accepts any regular PDF; encrypted or malformed PDFs fail with a clear error
- XRechnung output is XML-only by design (that is the standard); the PDF produced in that
  mode is a human-readable preview. XRechnung additionally requires `buyerReference`,
  seller `contactName`/`contactEmail`/`contactPhone`, buyer `electronicAddress`, and
  payment details — the validation report will tell you exactly what is missing
- Generation typically takes 10–30 s (JVM + FOP rendering); validation 5–15 s

### Pricing events

| Event | Meaning |
|---|---|
| `invoice-generated` | One e-invoice generated (includes embedded validation) |
| `invoice-validated` | One file validated |
| `xml-extracted` | One XML extracted from a PDF |

# Actor input Schema

## `mode` (type: `string`):

What to do: **generate** a new e-invoice from JSON, **validate** an existing e-invoice (PDF or XML), or **extract** the embedded XML from a Factur-X/ZUGFeRD PDF.

## `invoice` (type: `object`):

The invoice as JSON. Required: `number`, `issueDate` (YYYY-MM-DD), `currency`, `seller` {name, countryCode, vatId…}, `buyer` {…}, `lines` \[{name, quantity, unitPrice, vatRate}]. Optional: `dueDate`, `note`, `buyerReference`, `orderReference`, `deliveryDate`, `paidAmount`, `payment` {iban, bic, terms, reference}, per-line `unitCode`, `vatCategory` (S/Z/E/AE/K/G), `description`. Totals and VAT breakdown are computed automatically.

## `profile` (type: `string`):

Conformance profile of the generated invoice. `en16931` (default) satisfies both the French Factur-X and German ZUGFeRD requirements; `xrechnung` produces the XML-only German federal flavour (CII syntax, XRechnung 3.0).

## `basePdf` (type: `string`):

Your own invoice PDF (URL, data: URI, or base64). It is converted to PDF/A-3 and the XML is embedded into it, so the invoice keeps your branding. If omitted, a clean standardized PDF is rendered from the data.

## `language` (type: `string`):

Language of the rendered PDF labels (only used when no basePdf is given).

## `outputUbl` (type: `boolean`):

Additionally convert the invoice to UBL 2.1 syntax (used by Peppol BIS Billing and many national platforms).

## `validateResult` (type: `boolean`):

Run the full EN 16931 schematron validation on the generated invoice and include the report in the output. Recommended.

## `filename` (type: `string`):

Base name for the generated files (extension added automatically).

## `file` (type: `string`):

For validate and extract modes: the e-invoice to check — a URL, data: URI, base64 string, or (for validation) raw XML pasted directly. PDF and XML are auto-detected.

## Actor input object example

```json
{
  "mode": "generate",
  "invoice": {
    "number": "INV-2026-0042",
    "issueDate": "2026-08-08",
    "dueDate": "2026-09-07",
    "currency": "EUR",
    "note": "Thank you for your business.",
    "seller": {
      "name": "Atelier Lumière SARL",
      "street": "12 Rue de la Paix",
      "city": "Paris",
      "zip": "75002",
      "countryCode": "FR",
      "vatId": "FR40303265045",
      "registrationId": "30326504500014",
      "contactName": "Marie Dupont",
      "contactEmail": "billing@atelier-lumiere.example",
      "electronicAddress": "billing@atelier-lumiere.example"
    },
    "buyer": {
      "name": "Bau & Technik GmbH",
      "street": "Torstrasse 1",
      "city": "Berlin",
      "zip": "10115",
      "countryCode": "DE",
      "vatId": "DE123456789"
    },
    "payment": {
      "iban": "FR7630006000011234567890189",
      "bic": "AGRIFRPP",
      "terms": "Payable within 30 days."
    },
    "lines": [
      {
        "name": "UX design sprint",
        "quantity": 3,
        "unitCode": "DAY",
        "unitPrice": 850,
        "vatRate": 20
      },
      {
        "name": "Design system licence",
        "quantity": 1,
        "unitPrice": 490,
        "vatRate": 20
      }
    ]
  },
  "profile": "en16931",
  "language": "en",
  "outputUbl": false,
  "validateResult": true,
  "filename": "invoice"
}
```

# Actor output Schema

## `files` (type: `string`):

No description

## `result` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "invoice": {
        "number": "INV-2026-0042",
        "issueDate": "2026-08-08",
        "dueDate": "2026-09-07",
        "currency": "EUR",
        "note": "Thank you for your business.",
        "seller": {
            "name": "Atelier Lumière SARL",
            "street": "12 Rue de la Paix",
            "city": "Paris",
            "zip": "75002",
            "countryCode": "FR",
            "vatId": "FR40303265045",
            "registrationId": "30326504500014",
            "contactName": "Marie Dupont",
            "contactEmail": "billing@atelier-lumiere.example",
            "electronicAddress": "billing@atelier-lumiere.example"
        },
        "buyer": {
            "name": "Bau & Technik GmbH",
            "street": "Torstrasse 1",
            "city": "Berlin",
            "zip": "10115",
            "countryCode": "DE",
            "vatId": "DE123456789"
        },
        "payment": {
            "iban": "FR7630006000011234567890189",
            "bic": "AGRIFRPP",
            "terms": "Payable within 30 days."
        },
        "lines": [
            {
                "name": "UX design sprint",
                "quantity": 3,
                "unitCode": "DAY",
                "unitPrice": 850,
                "vatRate": 20
            },
            {
                "name": "Design system licence",
                "quantity": 1,
                "unitPrice": 490,
                "vatRate": 20
            }
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("josefbednar/factur-x-zugferd-e-invoice").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "invoice": {
        "number": "INV-2026-0042",
        "issueDate": "2026-08-08",
        "dueDate": "2026-09-07",
        "currency": "EUR",
        "note": "Thank you for your business.",
        "seller": {
            "name": "Atelier Lumière SARL",
            "street": "12 Rue de la Paix",
            "city": "Paris",
            "zip": "75002",
            "countryCode": "FR",
            "vatId": "FR40303265045",
            "registrationId": "30326504500014",
            "contactName": "Marie Dupont",
            "contactEmail": "billing@atelier-lumiere.example",
            "electronicAddress": "billing@atelier-lumiere.example",
        },
        "buyer": {
            "name": "Bau & Technik GmbH",
            "street": "Torstrasse 1",
            "city": "Berlin",
            "zip": "10115",
            "countryCode": "DE",
            "vatId": "DE123456789",
        },
        "payment": {
            "iban": "FR7630006000011234567890189",
            "bic": "AGRIFRPP",
            "terms": "Payable within 30 days.",
        },
        "lines": [
            {
                "name": "UX design sprint",
                "quantity": 3,
                "unitCode": "DAY",
                "unitPrice": 850,
                "vatRate": 20,
            },
            {
                "name": "Design system licence",
                "quantity": 1,
                "unitPrice": 490,
                "vatRate": 20,
            },
        ],
    } }

# Run the Actor and wait for it to finish
run = client.actor("josefbednar/factur-x-zugferd-e-invoice").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "invoice": {
    "number": "INV-2026-0042",
    "issueDate": "2026-08-08",
    "dueDate": "2026-09-07",
    "currency": "EUR",
    "note": "Thank you for your business.",
    "seller": {
      "name": "Atelier Lumière SARL",
      "street": "12 Rue de la Paix",
      "city": "Paris",
      "zip": "75002",
      "countryCode": "FR",
      "vatId": "FR40303265045",
      "registrationId": "30326504500014",
      "contactName": "Marie Dupont",
      "contactEmail": "billing@atelier-lumiere.example",
      "electronicAddress": "billing@atelier-lumiere.example"
    },
    "buyer": {
      "name": "Bau & Technik GmbH",
      "street": "Torstrasse 1",
      "city": "Berlin",
      "zip": "10115",
      "countryCode": "DE",
      "vatId": "DE123456789"
    },
    "payment": {
      "iban": "FR7630006000011234567890189",
      "bic": "AGRIFRPP",
      "terms": "Payable within 30 days."
    },
    "lines": [
      {
        "name": "UX design sprint",
        "quantity": 3,
        "unitCode": "DAY",
        "unitPrice": 850,
        "vatRate": 20
      },
      {
        "name": "Design system licence",
        "quantity": 1,
        "unitPrice": 490,
        "vatRate": 20
      }
    ]
  }
}' |
apify call josefbednar/factur-x-zugferd-e-invoice --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,josefbednar/factur-x-zugferd-e-invoice"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/HfS6JA3TLKEoeHdiZ/builds/daefauSbmqlJt4dbW/openapi.json
