# E-Invoice Reader & Converter: XRechnung, ZUGFeRD, Peppol (`bahs/e-invoice-reader-converter`) Actor

Read XRechnung, ZUGFeRD / Factur-X (XML or PDF) and Peppol UBL e-invoices into clean JSON or a readable HTML page, convert between formats, and generate EN 16931 invoices from JSON.

- **URL**: https://apify.com/bahs/e-invoice-reader-converter.md
- **Developed by:** [Sergei Bakhmetev](https://apify.com/bahs) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 document processeds

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## E-Invoice Reader & Converter — XRechnung, ZUGFeRD, Factur-X, Peppol

Turn European e-invoices into clean JSON or a readable page, convert between formats, and generate compliant XML from JSON.

E-invoicing is becoming mandatory across Europe: Germany requires businesses to **receive** XRechnung / ZUGFeRD since 2025
and to **issue** them from 2027–2028; Belgium, Poland and France follow. Many small businesses now get XML invoices they
cannot read, and many apps need to produce XRechnung, Peppol or Factur-X without building a compliance stack. This Actor
does both.

### What it does

| Mode | Input | Output |
|---|---|---|
| `parse` | URL of an XML invoice or a ZUGFeRD / Factur-X PDF | Structured JSON: parties, lines, VAT, totals, payment details, plus a validation report |
| `render` | Same as above | A clean, printable HTML page in the key-value store |
| `transform` | Same as above + `targetFormat` | The invoice rewritten in another format (e.g. ZUGFeRD → Peppol BIS), stored as XML |
| `convert` | Invoice JSON + `targetFormat` | XRechnung / Peppol BIS / Factur-X XML. Line amounts, VAT breakdown and totals are calculated for you |

**Formats:** XRechnung 3.0 (UBL and CII), Peppol BIS Billing 3.0, Factur-X / ZUGFeRD 2.x profile EN 16931 (XML, and
reading the XML embedded in a hybrid PDF), EN 16931 UBL. Invoices and credit notes.

**Tested on official reference data:** all 86 documents of the KoSIT XRechnung test suite are read and converted to
XRechnung UBL and CII, and the official KoSIT validator accepts the result for 85 of them (the remaining one uses the
XRechnung Extension, which is not supported yet). The embedded invoice is found in every one of the 61 official FeRD
ZUGFeRD 2.5.2 sample PDFs.

### Try it

Press **Start**: the input is prefilled with two public reference invoices — an XRechnung test invoice published by KoSIT
and a ZUGFeRD sample PDF published by FeRD. Switch the mode to `convert` to generate XML from the prefilled JSON invoice.

### Example input

```json
{
  "mode": "parse",
  "documentUrls": ["https://example.com/invoices/RE-2026-001.xml"],
  "includeHtml": true
}
```

### Example output (one dataset item per document)

```json
{
  "source": "https://example.com/invoices/RE-2026-001.xml",
  "ok": true,
  "number": "RE-2026-001",
  "format": "XRechnung (UBL)",
  "fromPdf": false,
  "invoice": { "number": "RE-2026-001", "issueDate": "2026-11-01", "currency": "EUR", "seller": { "name": "..." }, "totals": { "payableAmount": 1190.00 } },
  "validation": { "isValid": true, "errorCount": 0, "warningCount": 0, "issues": [] },
  "htmlUrl": "https://api.apify.com/v2/key-value-stores/.../records/RE-2026-001-a1b2c3.html"
}
```

A document that cannot be read gives an item with `"ok": false` and an `error` that says why — for example a PDF without
an embedded invoice, or a ZUGFeRD 1.0 invoice (not supported).

### Validation

Every result carries a fast built-in check of the most common EN 16931, XRechnung (BR-DE) and Peppol rules: mandatory
fields, totals, VAT arithmetic, code lists. Rule ids are the official ones (BR-…, BR-DE-…, PEPPOL-…) where the check
matches the official rule, `IB-…` for our own checks. It is a pre-check, not the official schematron validation. The
official validation (KoSIT validator with the XRechnung, EN 16931 and Peppol BIS rules) is part of the InvoiceBridge REST
API.

**No silent data loss:** when a source invoice contains data the JSON model does not carry (for example a delivery period
or an attached document), the report lists each of them as an `IB-DROPPED` warning with the EN 16931 term, so you know
exactly what a conversion leaves out.

### Pricing

Pay per event: you pay per successfully processed document (event `document-processed`). Documents that fail are not
charged. The run stops before it would exceed your maximum charge per run.

### Privacy

Documents are processed in memory during the run and are not stored by us. Results are written only to your own Apify
storage (dataset and key-value store).

# Actor input Schema

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

parse = e-invoice to JSON; render = e-invoice to a readable HTML page; transform = rewrite an e-invoice in another format; convert = generate e-invoice XML from JSON.

## `documentUrls` (type: `array`):

Links to XML invoices (XRechnung, Peppol BIS / UBL, Factur-X / ZUGFeRD CII) or hybrid PDFs with an embedded invoice (Factur-X / ZUGFeRD 2.x), up to 20 MB each. Used by parse, render and transform. The prefilled examples are public reference invoices: an official XRechnung test invoice (KoSIT) and an official ZUGFeRD sample PDF (FeRD).

## `invoices` (type: `array`):

Invoices in InvoiceBridge JSON (same as the REST API's /v1/convert body). Used by convert. Line amounts, VAT breakdown and totals are calculated when omitted.

## `targetFormat` (type: `string`):

Output format for transform and convert.

## `includeHtml` (type: `boolean`):

parse mode: also save a human-readable HTML page of each invoice to the key-value store (link in htmlUrl).

## Actor input object example

```json
{
  "mode": "parse",
  "documentUrls": [
    "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
    "https://raw.githubusercontent.com/ZUGFeRD/mustangproject/b0c60e456e63596b3ec3ac76e94374dc6e109c4f/library/src/test/resources/ZF252_Beispiele/3.%20EN16931/E05_Einfach/E05_01_Einfach_fx.pdf"
  ],
  "invoices": [
    {
      "number": "INV-1001",
      "issueDate": "2026-11-04",
      "dueDate": "2026-12-04",
      "currency": "EUR",
      "buyerReference": "991-12345-67",
      "seller": {
        "name": "Example Software GmbH",
        "vatId": "DE123456789",
        "electronicAddress": {
          "value": "DE123456789",
          "scheme": "9930"
        },
        "address": {
          "line1": "Hauptstraße 1",
          "city": "Berlin",
          "postalCode": "10115",
          "countryCode": "DE"
        },
        "contact": {
          "name": "Billing",
          "phone": "+49 30 000000",
          "email": "billing@example.com"
        }
      },
      "buyer": {
        "name": "Kunde AG",
        "vatId": "DE987654321",
        "electronicAddress": {
          "value": "DE987654321",
          "scheme": "9930"
        },
        "address": {
          "line1": "Marktplatz 3",
          "city": "München",
          "postalCode": "80331",
          "countryCode": "DE"
        }
      },
      "payment": {
        "meansCode": "58",
        "accounts": [
          {
            "id": "DE02120300000000202051"
          }
        ],
        "remittanceInformation": "INV-1001"
      },
      "lines": [
        {
          "name": "Consulting",
          "quantity": 8,
          "unitCode": "HUR",
          "netPrice": 120,
          "vatCategory": "S",
          "vatRate": 19
        }
      ]
    }
  ],
  "targetFormat": "peppol-bis",
  "includeHtml": false
}
```

# Actor output Schema

## `results` (type: `string`):

One item per document: ok, invoice number, format, validation report, links to the XML / HTML files, or the error.

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

Converted e-invoice XML (transform, convert) and HTML renderings (render, parse with includeHtml).

# 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 = {
    "documentUrls": [
        "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
        "https://raw.githubusercontent.com/ZUGFeRD/mustangproject/b0c60e456e63596b3ec3ac76e94374dc6e109c4f/library/src/test/resources/ZF252_Beispiele/3.%20EN16931/E05_Einfach/E05_01_Einfach_fx.pdf"
    ],
    "invoices": [
        {
            "number": "INV-1001",
            "issueDate": "2026-11-04",
            "dueDate": "2026-12-04",
            "currency": "EUR",
            "buyerReference": "991-12345-67",
            "seller": {
                "name": "Example Software GmbH",
                "vatId": "DE123456789",
                "electronicAddress": {
                    "value": "DE123456789",
                    "scheme": "9930"
                },
                "address": {
                    "line1": "Hauptstraße 1",
                    "city": "Berlin",
                    "postalCode": "10115",
                    "countryCode": "DE"
                },
                "contact": {
                    "name": "Billing",
                    "phone": "+49 30 000000",
                    "email": "billing@example.com"
                }
            },
            "buyer": {
                "name": "Kunde AG",
                "vatId": "DE987654321",
                "electronicAddress": {
                    "value": "DE987654321",
                    "scheme": "9930"
                },
                "address": {
                    "line1": "Marktplatz 3",
                    "city": "München",
                    "postalCode": "80331",
                    "countryCode": "DE"
                }
            },
            "payment": {
                "meansCode": "58",
                "accounts": [
                    {
                        "id": "DE02120300000000202051"
                    }
                ],
                "remittanceInformation": "INV-1001"
            },
            "lines": [
                {
                    "name": "Consulting",
                    "quantity": 8,
                    "unitCode": "HUR",
                    "netPrice": 120,
                    "vatCategory": "S",
                    "vatRate": 19
                }
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bahs/e-invoice-reader-converter").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 = {
    "documentUrls": [
        "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
        "https://raw.githubusercontent.com/ZUGFeRD/mustangproject/b0c60e456e63596b3ec3ac76e94374dc6e109c4f/library/src/test/resources/ZF252_Beispiele/3.%20EN16931/E05_Einfach/E05_01_Einfach_fx.pdf",
    ],
    "invoices": [{
            "number": "INV-1001",
            "issueDate": "2026-11-04",
            "dueDate": "2026-12-04",
            "currency": "EUR",
            "buyerReference": "991-12345-67",
            "seller": {
                "name": "Example Software GmbH",
                "vatId": "DE123456789",
                "electronicAddress": {
                    "value": "DE123456789",
                    "scheme": "9930",
                },
                "address": {
                    "line1": "Hauptstraße 1",
                    "city": "Berlin",
                    "postalCode": "10115",
                    "countryCode": "DE",
                },
                "contact": {
                    "name": "Billing",
                    "phone": "+49 30 000000",
                    "email": "billing@example.com",
                },
            },
            "buyer": {
                "name": "Kunde AG",
                "vatId": "DE987654321",
                "electronicAddress": {
                    "value": "DE987654321",
                    "scheme": "9930",
                },
                "address": {
                    "line1": "Marktplatz 3",
                    "city": "München",
                    "postalCode": "80331",
                    "countryCode": "DE",
                },
            },
            "payment": {
                "meansCode": "58",
                "accounts": [{ "id": "DE02120300000000202051" }],
                "remittanceInformation": "INV-1001",
            },
            "lines": [{
                    "name": "Consulting",
                    "quantity": 8,
                    "unitCode": "HUR",
                    "netPrice": 120,
                    "vatCategory": "S",
                    "vatRate": 19,
                }],
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("bahs/e-invoice-reader-converter").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 '{
  "documentUrls": [
    "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
    "https://raw.githubusercontent.com/ZUGFeRD/mustangproject/b0c60e456e63596b3ec3ac76e94374dc6e109c4f/library/src/test/resources/ZF252_Beispiele/3.%20EN16931/E05_Einfach/E05_01_Einfach_fx.pdf"
  ],
  "invoices": [
    {
      "number": "INV-1001",
      "issueDate": "2026-11-04",
      "dueDate": "2026-12-04",
      "currency": "EUR",
      "buyerReference": "991-12345-67",
      "seller": {
        "name": "Example Software GmbH",
        "vatId": "DE123456789",
        "electronicAddress": {
          "value": "DE123456789",
          "scheme": "9930"
        },
        "address": {
          "line1": "Hauptstraße 1",
          "city": "Berlin",
          "postalCode": "10115",
          "countryCode": "DE"
        },
        "contact": {
          "name": "Billing",
          "phone": "+49 30 000000",
          "email": "billing@example.com"
        }
      },
      "buyer": {
        "name": "Kunde AG",
        "vatId": "DE987654321",
        "electronicAddress": {
          "value": "DE987654321",
          "scheme": "9930"
        },
        "address": {
          "line1": "Marktplatz 3",
          "city": "München",
          "postalCode": "80331",
          "countryCode": "DE"
        }
      },
      "payment": {
        "meansCode": "58",
        "accounts": [
          {
            "id": "DE02120300000000202051"
          }
        ],
        "remittanceInformation": "INV-1001"
      },
      "lines": [
        {
          "name": "Consulting",
          "quantity": 8,
          "unitCode": "HUR",
          "netPrice": 120,
          "vatCategory": "S",
          "vatRate": 19
        }
      ]
    }
  ]
}' |
apify call bahs/e-invoice-reader-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bahs/e-invoice-reader-converter"
        }
    }
}
```

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/GWfrI6XF9e2AZGghx/builds/UBNkai3AtavnQj1yh/openapi.json
