# XRechnung & ZUGFeRD Invoice Validator API (`kamerozkan/xrechnung-xml-batch-validator-api`) Actor

Validate XRechnung 3.0.x XML and ZUGFeRD 2.5 or Factur-X 1.09 XML/PDF with pinned rules and structured findings. Batch e-invoice validation and E-Rechnung Prüfung for accounts payable automation, Steuerberater workflows, ERP and einvoice pipelines via API, n8n, Make, or MCP agents.

- **URL**: https://apify.com/kamerozkan/xrechnung-xml-batch-validator-api.md
- **Developed by:** [Kamer Ozkan](https://apify.com/kamerozkan) (community)
- **Categories:** Developer tools, Business
- **Stats:** 1 total users, 0 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/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

## XRechnung & ZUGFeRD Invoice Validator API

[![KoSIT Validator](https://img.shields.io/badge/KoSIT_Validator-1.6.0-005ea8)](https://github.com/itplr-kosit/validator/releases/tag/v1.6.0)
[![XRechnung](https://img.shields.io/badge/XRechnung-3.0.2-0a7f5a)](https://github.com/itplr-kosit/validator-configuration-xrechnung/releases/tag/v2026-01-31)
[![ZUGFeRD](https://img.shields.io/badge/ZUGFeRD-2.5-6f42c1)](https://www.ferd-net.de/publikationen-produkte/publikationen/detailseite/zugferd-25-english)
[![Factur-X](https://img.shields.io/badge/Factur--X-1.09-8a2be2)](https://www.ferd-net.de/publikationen-produkte/publikationen/detailseite/zugferd-25-english)
[![veraPDF](https://img.shields.io/badge/veraPDF-1.30.2-1f6feb)](https://github.com/veraPDF/veraPDF-apps/releases/tag/v1.30.2)

Validate XRechnung XML and ZUGFeRD or Factur-X XML/PDF invoices through one API. Every evaluated invoice receives a deterministic technical assessment, structured findings, SHA-256 evidence, and the exact pinned rule versions.

> Technical validation only. `ACCEPTED` means every required validation layer accepted the submitted invoice. It does not establish legal or tax validity, authenticity, successful delivery, visible PDF versus XML equality, or recipient acceptance.

### What is validated

| Input | Required checks |
|---|---|
| XRechnung XML | KoSIT Validator 1.6.0 with XRechnung configuration `v2026-01-31` |
| ZUGFeRD or Factur-X CII XML | Exact profile allowlist, ZUGFeRD 2.5 XSD, and profile Schematron |
| ZUGFeRD or Factur-X PDF | PDF/A-3 with veraPDF, safe embedded XML extraction, XMP and attachment consistency, then the complete CII XML checks |

The hybrid PDF result is accepted only when all required layers pass. PDF/A compliance alone is never treated as a valid invoice.

Supported ZUGFeRD and Factur-X profiles:

- `MINIMUM`
- `BASIC_WL`
- `BASIC`
- `EN16931`
- `EXTENDED`

Legacy ZUGFeRD 2.0 guideline identifiers are recognized as their matching
profiles and validated against the same pinned rule set; this recognition is
an explicit allowlist entry, not a fuzzy match.

XRechnung CII remains on the pinned KoSIT path. Unsupported or lookalike guideline identifiers are not silently mapped to a profile.

### Quick start

The default input validates an official XRechnung sample:

```json
{
  "documents": [
    {
      "documentId": "xrechnung-sample",
      "fileName": "01.01a-INVOICE_ubl.xml",
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-01-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml"
    }
  ],
  "resultDetail": "FINDINGS",
  "maxFindingsPerDocument": 100,
  "storeXmlReport": false,
  "storeHtmlReport": false,
  "storePdfaReport": false,
  "storeExtractedInvoiceXml": false
}
```

Send a hybrid invoice as an HTTPS URL or base64:

```json
{
  "documents": [
    {
      "documentId": "supplier-invoice-1042",
      "fileName": "supplier-invoice-1042.pdf",
      "url": "https://example.com/signed/invoice-1042.pdf"
    }
  ],
  "resultDetail": "FINDINGS"
}
```

Each `documents` item must contain exactly one source field: `url`, `xml`, or `base64`. Console file upload and customer key-value store records are also supported.

The input and output schemas are agent-readable and work with the Apify API, MCP clients, Make, n8n, webhooks, and standard SDKs.

### Output

One dataset item is returned for every submitted entry. A technically rejected invoice is a successful validation, not a processing failure.

The two records below are verbatim field subsets from live Apify run `R9gep9fAWMbrVA96h` on build `0.0.9`, executed on 2026-07-29. Omitted fields were not reconstructed.

<details>
<summary>Live ACCEPTED result: official ZUGFeRD 2.5 EN16931 PDF</summary>

```json
{
  "inputIndex": 2,
  "documentId": "zugferd-en16931",
  "fileName": "E05_01_Einfach_fx.pdf",
  "processingStatus": "SUCCEEDED",
  "conformanceStatus": "ACCEPTED",
  "sourceFormat": "ZUGFERD_PDF",
  "validationFamily": "ZUGFERD",
  "syntax": "CII_INVOICE",
  "profile": "ZUGFERD_EN16931",
  "scenario": "ZUGFeRD 2.5 / Factur-X 1.09 EN16931",
  "versions": {
    "validator": "1.6.0",
    "configurationRelease": "2026-01-31",
    "xrechnung": "3.0.2",
    "mustang": "2.24.0",
    "veraPdf": "1.30.2",
    "zugferdRules": "2.5",
    "facturXRules": "1.09"
  },
  "counts": {
    "fatal": 0,
    "error": 0,
    "warning": 0,
    "information": 0
  },
  "findings": [],
  "findingsTruncated": false,
  "sha256": "c7c431a9e585942b1a1bcfdb611544b9663a21b1199d4d1dc5294cbf5cc3e90b",
  "embeddedXmlSha256": "239272bc8c226c8d7f6058fef48722a15a48808dc0536a702662fef24e809fc7",
  "container": {
    "type": "PDF_A_3",
    "pdfaStatus": "COMPLIANT",
    "pdfaProfile": "PDF/A-3u validation profile",
    "metadataStatus": "CONSISTENT",
    "embeddedFileName": "factur-x.xml",
    "embeddedFileBytes": 13377,
    "afRelationship": "Data",
    "mimeType": "text/xml",
    "visibleContentConsistency": "NOT_VERIFIED",
    "signatureStatus": "NOT_CHECKED"
  },
  "checkedAt": "2026-07-29T05:53:33.000214Z",
  "reports": {
    "validationXmlKey": "VALIDATION-REPORT-0003-zugferd-en16931.xml",
    "htmlKey": "VALIDATION-REPORT-0003-zugferd-en16931.html",
    "pdfaXmlKey": "VALIDATION-REPORT-0003-zugferd-en16931.pdfa.xml",
    "extractedInvoiceXmlKey": "VALIDATION-REPORT-0003-zugferd-en16931.invoice.xml"
  },
  "error": null
}
```

</details>

<details>
<summary>Live REJECTED result: non-compliant PDF/A-3 container</summary>

```json
{
  "inputIndex": 4,
  "documentId": "zugferd-invalid-pdfa",
  "fileName": "invalidPDF.pdf",
  "processingStatus": "SUCCEEDED",
  "conformanceStatus": "REJECTED",
  "sourceFormat": "ZUGFERD_PDF",
  "validationFamily": "ZUGFERD",
  "syntax": "CII_INVOICE",
  "profile": "ZUGFERD_EN16931",
  "scenario": "ZUGFeRD 2.5 / Factur-X 1.09 EN16931",
  "counts": {
    "fatal": 0,
    "error": 1,
    "warning": 3,
    "information": 0
  },
  "findings": [
    {
      "severity": "ERROR",
      "stage": "PDF_A",
      "ruleId": "ISO 19005-3:2012 6.2.4.3-2",
      "failedChecks": 5
    }
  ],
  "findingsTruncated": false,
  "sha256": "30b44b5ba1a0b38b8871c9bde2154bb3bdebc7b4a6f43d4579a5d46bf5634957",
  "embeddedXmlSha256": "5203ba77a991466a7fc65f144abbf3eb8b45082686ef9c10aa07c79513e73ada",
  "container": {
    "type": "PDF_A_3",
    "pdfaStatus": "NON_COMPLIANT",
    "pdfaProfile": "PDF/A-3u validation profile",
    "metadataStatus": "CONSISTENT",
    "embeddedFileName": "factur-x.xml",
    "embeddedFileBytes": 10248,
    "afRelationship": "Alternative",
    "mimeType": "text/xml",
    "visibleContentConsistency": "NOT_VERIFIED",
    "signatureStatus": "NOT_CHECKED"
  },
  "checkedAt": "2026-07-29T05:54:18.578934Z",
  "reports": {
    "validationXmlKey": "VALIDATION-REPORT-0005-zugferd-invalid-pdfa.xml",
    "htmlKey": "VALIDATION-REPORT-0005-zugferd-invalid-pdfa.html",
    "pdfaXmlKey": "VALIDATION-REPORT-0005-zugferd-invalid-pdfa.pdfa.xml",
    "extractedInvoiceXmlKey": "VALIDATION-REPORT-0005-zugferd-invalid-pdfa.invoice.xml"
  },
  "error": null
}
```

</details>

This Actor is also exposed to AI agents through Apify's MCP server
(mcp.apify.com): an agent can discover it by search and run it with the same
pay-per-event billing, with no separate integration.

### Pricing

- `invoice-validated`: `$0.004` for each invoice that produces an `ACCEPTED` or `REJECTED` result
- `apify-actor-start`: `$0.00005` per GB of Actor memory, charged automatically when a run starts, with a minimum of one event

`NOT_EVALUATED` processing failures do not trigger the invoice validation event. The Actor start charge still applies.

### Result semantics

| Processing | Conformance | Meaning | Charged validation event |
|---|---|---|---|
| `SUCCEEDED` | `ACCEPTED` | Every required pinned technical layer passed | Yes |
| `SUCCEEDED` | `REJECTED` | The invoice was evaluated and one or more required rules failed | Yes |
| `FAILED` | `NOT_EVALUATED` | Source, format, engine, timeout, report, or budget failure prevented a decision | No |

When pay-per-event pricing is active, only evaluated rows use the `invoice-validated` event. Processing failures are not charged.

### Optional reports

All optional records are off by default:

- `storeXmlReport`: KoSIT report or normalized ZUGFeRD XSD and Schematron report
- `storeHtmlReport`: human-readable validation report
- `storePdfaReport`: sanitized veraPDF XML report for hybrid PDFs
- `storeExtractedInvoiceXml`: complete XML extracted from a hybrid PDF

Returned report keys appear in the row's `reports` object. Raw reports and extracted XML can contain invoice data and follow the retention settings of the customer's Apify account.

### Security and limits

- Validation runs locally inside the Actor container.
- No invoice is sent to a third-party validation API.
- Raw invoice content is not copied to the output dataset or logs.
- HTTPS downloads block private, local, reserved, and cloud metadata targets.
- DTDs, entities, and external XML resources are blocked.
- PDF parsing runs in an isolated process with CPU, memory, file, and descriptor limits.
- XML Schema validation runs in a separate isolated process.
- Java validation stages have timeouts and bounded reports.
- Each XML is limited to 5 MiB.
- Each PDF is limited to 20 MiB and 100 pages.
- Each PDF can expose at most 16 unique embedded file specifications.
- A run can evaluate up to 100 XML invoices, up to 20 PDF invoices, and 100 MiB total input.
- Finding fields and the total returned findings payload are bounded.

Validation findings can quote an offending invoice value. Treat results and optional reports as sensitive invoice data.

### Pinned stack

| Component | Version |
|---|---|
| KoSIT Validator | `1.6.0` |
| XRechnung configuration | `v2026-01-31` |
| XRechnung | `3.0.2` |
| CEN Schematron | `1.3.15` |
| ZUGFeRD rules | `2.5` |
| Factur-X rules | `1.09` |
| Mustangproject rule bundle and Saxon runtime | `2.24.0` |
| veraPDF | `1.30.2` |

Docker builds verify downloaded engines against fixed SHA-256 checksums. ZUGFeRD decisions come from the release-pinned profile XSD and Schematron assets directly, avoiding unrelated wrapper heuristics.

### Release gates

The release suite covers:

- Official XRechnung accepted and rejected UBL/CII fixtures
- All 51 current FeRD ZUGFeRD 2.5 example PDF/XML pairs
- BASIC, EN16931, and EXTENDED official examples
- MINIMUM and BASIC\_WL compatibility fixtures
- PDF/A failure, XML Schema failure, Schematron failure, malformed XMP, ambiguous attachments, and digest consistency negatives

Official FeRD fixtures are downloaded only for release testing and are not redistributed in the production image.

### Current scope

This Actor does not verify:

- Whether visible PDF text equals the embedded XML
- Digital signatures or issuer authenticity
- Peppol delivery or recipient portal acceptance
- Tax treatment, legal validity, fraud, duplicates, or payment approval
- ZUGFeRD 1.x, generic CIUS, or EXTENDED-CTC-FR

### Common processing error codes

- `DOCUMENT_LIMIT_EXCEEDED`
- `PDF_RUN_LIMIT_REACHED`
- `SOURCE_FETCH_FAILED`
- `SOURCE_HTTP_ERROR`
- `SOURCE_TOO_LARGE`
- `UNSUPPORTED_MEDIA_TYPE`
- `PDF_MAGIC_INVALID`
- `PDF_ENCRYPTED`
- `XML_MALFORMED`
- `DOCTYPE_FORBIDDEN`
- `NO_SCENARIO_MATCH`
- `VALIDATION_TIMEOUT`
- `REPORT_PARSE_FAILED`
- `REPORT_TOO_LARGE`
- `VALIDATOR_EXECUTION_FAILED`
- `BUDGET_LIMIT_REACHED`
- `RUN_TIME_BUDGET_REACHED`

Rule failures remain in `findings` and produce `REJECTED`; they are not converted into processing errors.

### Official references

- [KoSIT Validator](https://github.com/itplr-kosit/validator)
- [XRechnung validator configuration](https://github.com/itplr-kosit/validator-configuration-xrechnung)
- [XRechnung test suite](https://github.com/itplr-kosit/xrechnung-testsuite)
- [ZUGFeRD 2.5 and Factur-X 1.09](https://www.ferd-net.de/publikationen-produkte/publikationen/detailseite/zugferd-25-english)
- [veraPDF validation documentation](https://docs.verapdf.org/cli/validation/)
- [Third-party licenses and notices](THIRD_PARTY_NOTICES.md)

### E-invoice validator family

Same engine, same output contract, one validator per market:
[Peppol BIS Billing](https://apify.com/kamerozkan/peppol-bis-preflight-validator) | [Poland KSeF FA(3)](https://apify.com/kamerozkan/poland-ksef-preflight-validator) | [France E-Invoice](https://apify.com/kamerozkan/france-einvoice-validator) | [Italy FatturaPA](https://apify.com/kamerozkan/italy-fatturapa-validator)

# Actor input Schema

## `invoiceFiles` (type: `array`):

Upload XRechnung XML, ZUGFeRD or Factur-X CII XML, or hybrid PDF/A-3 invoice files. Files are processed inside the Actor and are not copied to the output dataset.

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

Each object needs one source: url, xml, or base64. URL and base64 sources can contain XML or PDF. HTTPS URLs only. documentId and fileName are optional.

## `sourceKeyValueStoreId` (type: `string`):

Optional. Select a key-value store that contains XML or PDF records, then list the record keys below.

## `keyValueStoreKeys` (type: `array`):

Record keys to read from the selected source key-value store.

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

FINDINGS returns rule IDs, messages, and locations. SUMMARY returns only status and counts.

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

Caps the findings array without changing the total severity counts.

## `storeXmlReport` (type: `boolean`):

Optional. Stores the KoSIT or ZUGFeRD rules report in your run key-value store. Reports can contain invoice values.

## `storeHtmlReport` (type: `boolean`):

Optional. HTML reports contain the invoice content and are stored in your run key-value store.

## `storePdfaReport` (type: `boolean`):

Optional. For hybrid PDFs, stores the sanitized veraPDF XML report in your run key-value store.

## `storeExtractedInvoiceXml` (type: `boolean`):

Optional. For hybrid PDFs, stores the extracted invoice XML in your run key-value store. This record contains the complete invoice.

## Actor input object example

```json
{
  "documents": [
    {
      "documentId": "kosit-valid-sample",
      "fileName": "01.01a-INVOICE_ubl.xml",
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-01-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml"
    }
  ],
  "resultDetail": "FINDINGS",
  "maxFindingsPerDocument": 100,
  "storeXmlReport": false,
  "storeHtmlReport": false,
  "storePdfaReport": false,
  "storeExtractedInvoiceXml": false
}
```

# Actor output Schema

## `validationResults` (type: `string`):

No description

## `summary` (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 = {
    "documents": [
        {
            "documentId": "kosit-valid-sample",
            "fileName": "01.01a-INVOICE_ubl.xml",
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-01-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/xrechnung-xml-batch-validator-api").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": [{
            "documentId": "kosit-valid-sample",
            "fileName": "01.01a-INVOICE_ubl.xml",
            "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-01-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/xrechnung-xml-batch-validator-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    {
      "documentId": "kosit-valid-sample",
      "fileName": "01.01a-INVOICE_ubl.xml",
      "url": "https://raw.githubusercontent.com/itplr-kosit/xrechnung-testsuite/v2026-01-31/src/test/business-cases/standard/01.01a-INVOICE_ubl.xml"
    }
  ]
}' |
apify call kamerozkan/xrechnung-xml-batch-validator-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kamerozkan/xrechnung-xml-batch-validator-api",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/PtcUXR04GofVFXxb9/builds/1GSMwbp6WVkfXh5GV/openapi.json
