# E-Invoice Validator: XRechnung, ZUGFeRD, Factur-X (KoSIT) (`app-to-go/e-rechnung-pruefer`) Actor

Validate XRechnung, ZUGFeRD and Factur-X e-invoices with the latest official KoSIT rules, for mandatory e-invoicing in Germany from 2027. German fix hints.

- **URL**: https://apify.com/app-to-go/e-rechnung-pruefer.md
- **Developed by:** [Evgen Grebenyuk](https://apify.com/app-to-go) (community)
- **Categories:** Developer tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 invoice validateds

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

### What does E-Invoice Validator do?

**E-Invoice Validator** checks German and European e-invoices against the **current official KoSIT rules** and tells you, in plain words, what to fix. It uses the **latest rule version** (KoSIT validator 1.6.3 with XRechnung configuration 2026-08-31, as of October 2026) and is built for the **German e-invoicing obligation from 2027/2028**. It accepts **XRechnung 3.0.x**, **EN 16931** invoices in **UBL** and **UN/CEFACT CII** syntax, and **ZUGFeRD / Factur-X PDFs** with an embedded invoice XML. Every finding comes with the original rule message and a short **German correction hint** (`hint_de`), so accounting teams can act on it without reading Schematron.

Try it in 3 clicks: open the Actor, keep the prefilled example (two public files from the official KoSIT test suite) and press **Start**.

#### Why you need it

- **E-invoicing is mandatory in Germany.** Since 2025 every business must be able to receive e-invoices. From **2027** companies with more than €800,000 turnover must send them for B2B, from **2028** all companies. A PDF alone is no longer enough.
- **The rules change several times a year.** KoSIT publishes new validator configurations 2–3 times per year. This Actor pins the latest release (currently KoSIT validator 1.6.3 with XRechnung configuration 2026-08-31) and every result tells you which rule versions were used.
- **German hints instead of cryptic rule IDs.** `BR-DE-15` becomes “Käuferreferenz (BT-10) angeben, bei öffentlichen Auftraggebern die Leitweg-ID.”

#### Main features

- XRechnung 3.0.x (UBL and CII), including Extension and CVD
- EN 16931 UBL and CII
- ZUGFeRD 1.0 / 2.x and Factur-X PDFs: the embedded XML is extracted and checked; profiles without a KoSIT scenario (EXTENDED, BASIC, BASIC WL, MINIMUM, ZUGFeRD 1.0) are checked with Mustang
- Optional official KoSIT HTML test report per invoice
- Bulk mode: read thousands of invoices from a key-value store
- Runs on the Apify platform: API, schedules, webhooks, integrations (Make, Zapier, n8n) and MCP for AI agents

### How to use it

1. Click **Try for free** / **Start**.
2. Add your invoices under **Documents**: a `url`, the XML text in `xml`, or a PDF/XML file as `base64`.
3. Optionally choose `resultDetail` (`SUMMARY` or `FINDINGS`) and enable `htmlReport`.
4. Click **Start**. A run with a few invoices takes about 20–30 seconds (most of it is starting the validators).
5. Download the results from the **Output** tab or fetch them via the API.

For integrations, call the Actor via the API with your invoice as `base64` and read the dataset item. For large batches, upload the files to a key-value store and pass `kvStoreId` and `keys`.

### Input

| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| `documents` | array | yes, unless `kvStoreId` is used | Invoices; each entry has exactly one of `url`, `xml`, `base64` (max. 20 MB), optional `documentId`, `fileName` | see below |
| `kvStoreId` | string | no | Key-value store to read invoices from (bulk mode); pick it in the Console or pass its ID via the API | `aBcD1234eFgH5678i` |
| `keys` | array | no | Record keys in that store | `["inv-001.xml"]` |
| `resultDetail` | string | no | `SUMMARY` (conformance and counts) or `FINDINGS` (default) | `FINDINGS` |
| `maxFindingsPerDocument` | integer | no | Maximum listed findings per invoice, errors first (default 50) | `50` |
| `language` | string | no | Language of log messages (`de`, `en`) | `en` |
| `htmlReport` | boolean | no | Store the KoSIT HTML report per invoice (default `false`) | `true` |

<details><summary>Example input (JSON)</summary>

```
{
  "documents": [
    { "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml", "documentId": "example-ubl" },
    { "base64": "JVBERi0xLjcK...", "documentId": "INV-2026-0042", "fileName": "INV-2026-0042.pdf" }
  ],
  "resultDetail": "FINDINGS",
  "htmlReport": false
}
```

</details>

### Output

Each checked invoice is one dataset item. At the end of the run a `RUN_SUMMARY` item is added (and stored as `RUN_SUMMARY` in the key-value store). Example:

```
{
  "recordType": "DOCUMENT",
  "documentId": "example-ubl",
  "fileName": "01.01a-INVOICE_ubl.xml",
  "sha256": "74fb09c6…",
  "sourceFormat": "UBL",
  "profile": "XRechnung 3.0",
  "conformance": "VALID",
  "counts": { "error": 0, "warning": 0, "info": 1 },
  "findings": [
    {
      "ruleId": "BR-DE-TMP-32",
      "severity": "info",
      "message": "[BR-DE-TMP-32] Eine Rechnung sollte zur Angabe des Liefer-/Leistungsdatums …",
      "hint_de": "[BR-DE-TMP-32] Eine Rechnung sollte zur Angabe des Liefer-/Leistungsdatums …",
      "location": "/Invoice[1]"
    }
  ],
  "validator": "kosit",
  "versions": { "kosit": "1.6.3", "xrechnungConfig": "2026-08-31", "en16931": "1.3.16", "mustang": "2.26.0" },
  "checkedAt": "2026-10-18T18:47:18.538Z",
  "htmlReportKey": "report-0001-74fb09c609d5"
}
```

| Field | Description |
|---|---|
| `conformance` | `VALID`, `INVALID` or `NOT_EVALUATED` (file could not be read, e.g. not an invoice or a PDF without invoice XML) |
| `sourceFormat`, `profile` | Detected syntax (UBL, CII, ZUGFeRD-PDF, Factur-X) and profile (e.g. XRechnung 3.0, EN16931, EXTENDED) |
| `counts`, `findings` | Number of errors, warnings and infos; the findings with `ruleId`, `severity`, `message`, `hint_de` and XPath `location` |
| `validator` | `kosit` or `mustang` |
| `versions` | Rule and validator versions used for this check |
| `notEvaluatedReason` | Why a file was not evaluated (only for `NOT_EVALUATED`) |

### Pricing

#### How much does it cost?

This Actor uses **pay per event** pricing. You only pay for invoices that were actually checked:

| Event | Price |
|---|---|
| Actor start | $0.00005 per run start, charged once per GB of memory (default 2 GB = $0.0001 per run) |
| Invoice validated (`VALID` or `INVALID`) | $0.004 per invoice |
| HTML report stored | $0.002 per report |

Files that cannot be evaluated (`NOT_EVALUATED`) are **free**. Example with the default 2 GB of memory and without HTML reports: 1,000 invoices in one run cost about **$4.00** ($4.0001), a single invoice in its own run about $0.0041. Platform usage is included in these prices.

### Limits

- This Actor checks **technical and formal conformance** with XRechnung / EN 16931 / ZUGFeRD / Factur-X. It is **no tax or legal advice** and does not check whether the content of an invoice is correct (e.g. VAT treatment).
- URLs must be public `http(s)` addresses; private, internal and cloud-metadata addresses are refused, at most 3 redirects are followed, and a download stops at 20 MB or after 30 s. Refused URLs are reported as `NOT_EVALUATED` and not charged.
- At most **1,000 documents** per run (`documents` and `keys` together). Larger runs are refused with a clear message before anything is checked or charged; please split them into several runs. Invoices are loaded one at a time while they are checked (at most 4 in parallel), so every run fits into the default 2 GB memory. For large batches prefer `url` or a key-value store over inline `xml`/`base64`, because inline documents are part of the run input.
- Maximum file size is 20 MB per invoice. PDFs must contain the invoice XML as an embedded file (`factur-x.xml`, `zugferd-invoice.xml`, `xrechnung.xml`).
- PDF/A conformance of the visual PDF is not checked.

### Disclaimer

- This Actor is a **validation aid**. It is **no legal or tax advice** and does not replace a review by your tax advisor.
- Results are provided **without any warranty of completeness or correctness**. Validation is done with the official KoSIT validator and validator configuration in the versions listed in `versions`; the **official KoSIT rules and the applicable legal requirements are authoritative**. If our result differs from the official KoSIT validator, the official result prevails – please report it via the Issues tab.
- The German hints (`hint_de`) are simplified explanations of the original rule messages; the original `message` is authoritative.
- A `VALID` result only means the file meets the technical and formal rules checked. It does not confirm that the invoice content (amounts, VAT treatment, recipient) is correct or that the invoice will be accepted by the recipient.
- Use of this Actor is governed by the Apify Standard Actor Contract between you and the Actor creator.

### FAQ

#### Which rule version is used?

KoSIT validator 1.6.3 with the XRechnung validator configuration 2026-08-31 (XRechnung 3.0.2, EN 16931 rules 1.3.16) and Mustang 2.26.0 for ZUGFeRD / Factur-X profiles without a KoSIT scenario. Every result lists the versions used in the field `versions`.

#### Is this valid for the 2027 obligation?

The Actor checks invoices against the technical formats accepted for the German e-invoicing obligation (XRechnung and EN 16931 compliant ZUGFeRD / Factur-X). It shows whether a file meets these technical and formal rules; it does not decide whether your business or a single invoice falls under the obligation.

#### How often are rules updated?

KoSIT publishes new validator configurations several times a year. We check for new releases every week and update the Actor after testing; new rule releases are listed in the **Changelog** tab.

#### Is this tax advice?

No. This Actor is a validation aid and no legal or tax advice; see the **Disclaimer** above.

### Data protection

- Invoices are processed in memory and in a temporary folder that is deleted at the end of the run.
- Invoices passed inline as `xml` or `base64` are part of the run input. Apify stores the run input (record `INPUT`) in your account like any run input, according to your retention settings. If you do not want invoice content to be kept with the run, pass a `url` or a key-value store record and delete it after the run.
- You remain the controller of the personal data in your invoices; Apify processes it as your processor under its Data Processing Addendum. The Actor runs with limited permissions and only reads the key-value store you select; the Actor creator has no access to your runs or storages.
- The log contains only counts and versions, never invoice content.
- Nothing is stored except the check results in the dataset, `RUN_SUMMARY` and, if you enable it, the HTML report per invoice in your key-value store. The results contain rule messages, XPath locations and a SHA-256 hash of the file, not the invoice itself (rule messages may quote single field values, e.g. an invalid code).
- All storages belong to your Apify account and follow your retention settings.

### Data sources and licenses

- [KoSIT validator](https://github.com/itplr-kosit/validator), [XRechnung validator configuration](https://github.com/itplr-kosit/validator-configuration-xrechnung) and [XRechnung test suite](https://github.com/itplr-kosit/xrechnung-testsuite): Apache License 2.0.
- [EN 16931 Schematron rules](https://github.com/ConnectingEurope/eInvoicing-EN16931) (contained in the XRechnung configuration): EUPL 1.2.
- UBL 2.1 XML schemas (OASIS) and UN/CEFACT CII D16B XML schemas, contained in the XRechnung configuration.
- [Mustang](https://github.com/ZUGFeRD/mustangproject) (incl. Apache PDFBox) for ZUGFeRD / Factur-X: Apache License 2.0.
- This Actor is not affiliated with or endorsed by KoSIT, the European Commission or the Mustang project.

### Provider / Legal notice

Provided by app-to-go – Legal notice (Impressum): https://app-to-go.recordingbeats.com/impressum.html · Privacy policy: https://app-to-go.recordingbeats.com/datenschutz.html

### Support

- Found a bug or a file that is checked wrongly? Open an issue in the **Issues** tab, ideally with the `documentId`, `ruleId` and `versions` from the output (no real invoices, please).
- Need a custom integration (e.g. for your accounting software)? Contact us via the Issues tab.
- New rule releases are listed in the **Changelog** tab.

### Other Actors by app-to-go

| Actor | What it does |
|---|---|
| E-Invoice Reader (coming soon) | Extracts the data of XRechnung, ZUGFeRD and Factur-X invoices as structured JSON |

# Changelog

This Actor's version history is a separate document: https://apify.com/app-to-go/e-rechnung-pruefer/changelog.md

# Actor input Schema

## `documents` (type: `array`):

Invoices to check. Each entry needs exactly one of url, xml (XML text) or base64 (PDF or XML, max. 20 MB). At most 1,000 documents per run (together with keys). Optional: documentId and fileName, both are copied to the output.

## `kvStoreId` (type: `string`):

For bulk runs: read the documents from this key-value store (use together with keys). The Actor gets read access to this store only.

## `keys` (type: `array`):

Record keys in the key-value store above. At most 1,000 per run (together with documents).

## `resultDetail` (type: `string`):

SUMMARY returns conformance and counts only, FINDINGS also lists the individual findings.

## `maxFindingsPerDocument` (type: `integer`):

Upper limit of listed findings per document (errors first).

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

Language of log messages. Findings always contain the original rule message and the German hint (hint_de).

## `htmlReport` (type: `boolean`):

Store the official KoSIT HTML test report per checked document in the default key-value store (charged as html-report, $0.002 each).

## Actor input object example

```json
{
  "documents": [
    {
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
      "documentId": "example-ubl"
    },
    {
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_uncefact.xml",
      "documentId": "example-cii"
    }
  ],
  "resultDetail": "FINDINGS",
  "maxFindingsPerDocument": 50,
  "language": "de",
  "htmlReport": false
}
```

# Actor output Schema

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

Validation result per invoice (conformance VALID / INVALID / NOT_EVALUATED, format, profile, rule message counts) and a final RUN_SUMMARY row, in the overview table view.

## `summary` (type: `string`):

Run summary as JSON: number of checked, valid, invalid and not evaluated invoices, HTML reports, rule versions and duration.

## `htmlReports` (type: `string`):

Human-readable HTML report per invoice (only when the htmlReport input is on); the record key is in the htmlReportKey field of each result row.

# 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 = {
    "documents": [
        {
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
            "documentId": "example-ubl"
        },
        {
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_uncefact.xml",
            "documentId": "example-cii"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("app-to-go/e-rechnung-pruefer").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 = { "documents": [
        {
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
            "documentId": "example-ubl",
        },
        {
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_uncefact.xml",
            "documentId": "example-cii",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("app-to-go/e-rechnung-pruefer").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 '{
  "documents": [
    {
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
      "documentId": "example-ubl"
    },
    {
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-08-31/src/test/business-cases/standard/01.01a-INVOICE_uncefact.xml",
      "documentId": "example-cii"
    }
  ]
}' |
apify call app-to-go/e-rechnung-pruefer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,app-to-go/e-rechnung-pruefer"
        }
    }
}
```

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/2qY1RpPFflYJ7dvd0/builds/jtQyhWyBN9xS7lE4E/openapi.json
