Automation MCP Server Features Blog Pricing Contact
Integration ZUGFeRD Format

Mustangproject Alternatives: An Honest Comparison for ZUGFeRD and Factur-X Teams

Mustangproject is the strongest open-source e-invoicing library in any ecosystem, and this comparison starts by saying so. What follows is the part the quick-start never shows: a capability matrix against a managed REST API, the real operating cost of the PDFBox, Saxon, and veraPDF stack, the specification treadmill every FeRD and KoSIT release restarts, and a concrete migration path from the Invoice builder classes to one HTTP call.

Nobody searches for a Mustangproject alternative because Mustangproject is bad software. It is the most capable open-source e-invoicing library in any ecosystem, and if you are evaluating it, using it, or inheriting a system built on it, you already know that. The search usually starts somewhere else: a security scanner flagging transitive dependencies, a FeRD release forcing an unplanned upgrade, a PDF that fails a recipient's conformance check, or a supplier PDF with no embedded XML that the library cannot read by design.

This guide is the full comparison: what the library genuinely does well, a capability matrix against the InvoiceXML ZUGFeRD API, the operating cost that only shows up after the prototype, and a concrete migration path, including a field-by-field mapping from the Mustangproject builder classes to the API request model. One disclosure up front: this comparison is written by the maker of one of the alternatives, which is exactly why every Mustangproject fact below was verified against the official repository and mustangproject.org as of version 2.24.0 (June 2026).

If you want the language-specific integration walkthroughs instead, the guides to ZUGFeRD in Java, Factur-X in Java, and XRechnung in Java cover the full lifecycle with runnable code. This page is about the decision itself.

What Mustangproject does well

Credit where it is due, because the comparison is meaningless without it:

A decade of continuous maintenance. Mustangproject shipped its first release in 2014, targeting the original ZUGFeRD 1.0, and has been maintained by Jochen Stärk and contributors ever since. Releases arrive every month or two; version 2.24.0 landed on June 12, 2026 with Factur-X 1.09 and ZUGFeRD 2.5.0 support. Apache-2.0 licensed, free for commercial use, on Maven Central. In open-source e-invoicing, that longevity is the exception, not the rule.

Reference-grade format coverage. It writes, reads, and validates ZUGFeRD 1 and 2.x, Factur-X, and CII XRechnung (3.0.2 as of 2.24.0), plus Order-X for purchase orders. Its Invoice, TradeParty, and Item model builds the CII XML, the ZUGFeRDExporterFromA1 and ZUGFeRDExporterFromA3 classes embed it into PDF/A-3, and importer classes read the XML back out of hybrid PDFs. Many German invoicing products are built on exactly these classes.

In-process validation that no other ecosystem matches. Because Saxon-HE is a native Java library, Mustangproject's validator can run the official Schematron rule sets in-process and add PDF/A checking through embedded veraPDF. .NET, Node.js, Python, and PHP have no equivalent of this; their XSLT tooling cannot execute the official rules locally at all. If in-process validation on the JVM is a hard requirement, Mustangproject is realistically the only game in town.

A genuinely useful CLI. The Mustang command line tool extracts XML from hybrids, combines XML with PDF/A input, validates files from any producer, upgrades ZUGFeRD 1.0 XML to 2.x, converts CII to UBL, and renders visualizations. For one-off jobs and format archaeology it is a fine tool to have on disk.

So the question this page answers is not whether Mustangproject is good. It is whether your team should be the one operating the compliance machinery it hands you, and that question is best answered with the full picture on the table.


Capability matrix

Mustangproject capabilities are as documented for version 2.24.0 (June 2026); API capabilities link to their documentation.

CapabilityMustangproject 2.24InvoiceXML REST API
ZUGFeRD / Factur-X XML generationYes, via the Invoice model and pull providersYes, JSON in, validated document out (/v1/create/zugferd, /v1/create/facturx)
Embedding XML into PDF/A-3Yes, from PDF/A input via the exporter classesYes, generated layout or your own PDF
PDF/A-3 conformance of arbitrary input PDFsExpects PDF/A input; non-conformant PDFs can be forced with ignorePDFAErrors() without a conformance guaranteeHandled server-side; output is validated before it is returned
Reading hybrid PDFs (embedded XML)Yes, importer classesYes, /v1/extract/json and /v1/extract/xml
Reading plain supplier PDFs (no embedded XML)No, structured input requiredYes, AI parsing with confidence scores (/v1/parse/json)
Embedded attachments (BG-24)Attachment embedding via FileAttachment in the modelEmbedding on create plus extraction to ZIP (/v1/extract/attachments)
ValidationXSD, Schematron, and PDF/A in-process via the separate validator artifact (Saxon-HE, veraPDF)Official rule sets server-side, JSON findings with rule ids and field paths (/v1/validate/zugferd)
Validation currencyThe artifacts bundled with the release you ship; newer rules arrive with the next library versionCurrent FeRD, KoSIT, and CEN artifacts live server-side, applied before their effective dates
XRechnungCII syntax (3.0.2); UBL only by converting generated CII via the bundled cii2ubl converterNative CII and UBL (/v1/create/xrechnung, /v1/create/ubl with the xrechnung profile)
Peppol BISNo document creation, no network transmissionPeppol BIS 3.0 UBL via /v1/create/ubl
Rendering previewsXML to HTML (experimental for Extended profiles) and XML to PDF (German-language output)/v1/render/xrechnung/to/pdf and /v1/render/cii/to/pdf
Infrastructure requiredA JVM service carrying PDFBox, Saxon-HE, veraPDF, Apache FOP, and their transitive graphAny HTTP client; zero compliance dependencies in your build
Specification updatesWatch the announcement, wait for the release, bump, retest, redeployLive server-side with no change on your side
SupportCommunity, via GitHub issuesProfessional support; missing features integrated on request

Two rows in that table decide most evaluations, and neither is about features. Validation currency and specification updates are about time: who does the recurring work, and on whose calendar. The next two sections put numbers on that.


The dependency stack you operate

Adding Mustangproject to a build is one Maven coordinate. What that coordinate pulls in, per the project's own poms at version 2.24.0, is the actual operating surface:

Apache PDFBox 3.0.8 plus its preflight module for PDF manipulation and PDF/A analysis. Saxon-HE 12.10 to execute the Schematron rule sets as XSLT. veraPDF for PDF/A validation in the validator artifact. Apache FOP for PDF rendering of visualizations. Around them: Jackson, dom4j, the helger Schematron and CII-to-UBL libraries, and Jakarta XML binding, on Java 11 or later.

Every one of those projects has its own release cadence, its own CVE stream, and its own compatibility story across JDK upgrades. Adopting the library makes that graph part of your application: your security scanner reports on it, your dependency-convergence rules negotiate with it (particularly when your application already uses PDFBox or Jackson at a different version), and your team upgrades it, whether or not anything about your invoices changed. None of this is a flaw in Mustangproject; it is the nature of doing PDF forensics, XSLT 2.0, and archival conformance in-process. The stack is the price of admission.

The API route removes the entire graph. The compliance machinery runs server-side, and what remains in your build is the HTTP client your runtime already ships. There is no compliance-related dependency left to scan, converge, or upgrade.


The specification treadmill

The deeper cost is the update cycle that European e-invoicing imposes on everyone. FeRD and FNFE-MPE publish new ZUGFeRD and Factur-X versions, KoSIT revises XRechnung on a regular schedule, and CEN maintains the EN 16931 artifacts underneath all of them. Each publication starts the same sequence for a library-based stack: watch for the announcement, wait for the library release that supports it, bump the version, retest your pipeline, and redeploy every service that touches invoices.

Mustangproject handles its side of this admirably, and its own release history shows the treadmill in motion: XRechnung 3.0.2 validation arrived with 2.19.0 in August 2025, ZUGFeRD 2.4 and Factur-X 1.08 with 2.21.0 in December 2025, and ZUGFeRD 2.5.0 with Factur-X 1.09 in version 2.24.0 in June 2026. Three specification-driven upgrades in eleven months, each one a mandatory library bump, regression test, and redeploy for every team tracking compliance, multiplied by every service that issues or validates invoices. The window between a specification taking effect and your upgraded build reaching production is compliance risk you carry, every cycle, forever.

With the API there is no cycle to run. The current FeRD, KoSIT, and CEN artifacts are applied server-side before their effective dates; your integration does not change, and nothing on your side needs monitoring, bumping, or redeploying. The team whose full-time job is e-invoicing compliance absorbs the treadmill so yours does not.


Migrating from Mustangproject

This is the part a comparison table cannot carry: what the switch actually involves. The short answer is less than most teams expect, because the API's request model covers the same semantic ground as Mustangproject's invoice model, and the API computes totals and the VAT breakdown from line items, so the migration is a mapping exercise, not a redesign. Three subsections: the concept mapping, the same invoice written both ways, and the migration sequence.


Mapping the API surface

The table maps the Mustangproject classes and setters a typical generation pipeline uses onto the JSON request fields of POST /v1/create/zugferd (the identical model serves /v1/create/facturx and /v1/create/xrechnung):

Mustangproject conceptInvoiceXML request field or endpoint
new Invoice().setNumber("RE-2026-001")invoice.invoiceNumber
setIssueDate(...), setDueDate(...)invoice.issueDate, invoice.dueDate
setSender(new TradeParty(name, street, zip, city, country))invoice.seller.name and invoice.seller.postalAddress (line1, postCode, city, country)
TradeParty.addVATID("DE...")invoice.seller.vatIdentifier
TradeParty.setContact(new Contact(name, phone, email))invoice.seller.contact (name, phone, email)
TradeParty.addBankDetails(new BankDetails(iban, bic))invoice.paymentDetails.paymentAccountIdentifier
setRecipient(new TradeParty(...))invoice.buyer (same shape as the seller)
setReferenceNumber(...) (the Leitweg-ID)invoice.buyerReference
new Product(name, description, unitCode, vatPercent)lines[].item.name, lines[].unitCode, lines[].vatInformation.rate
new Item(product, price, quantity)lines[].priceDetails.netPrice, lines[].quantity
ZUGFeRD2PullProvider + Profiles.getByName(...)The endpoint choice: /v1/create/zugferd, /v1/create/facturx, or /v1/create/xrechnung
ZUGFeRDExporterFromA1 / FromA3 + export(...)Not needed: the create endpoints return a finished PDF/A-3
ZUGFeRDImporter / ZUGFeRDInvoiceImporterPOST /v1/extract/json (or /v1/extract/xml for the raw CII)
ZUGFeRDValidator.validate(...)POST /v1/validate/zugferd
ZUGFeRDVisualizerPOST /v1/render/cii/to/pdf or /v1/render/xrechnung/to/pdf

Everything that has no row on the right side is work that disappears rather than moves: sourcing a PDF/A-conformant input file, wiring the validator artifact, and keeping the Schematron and PDF/A tooling current.


The same invoice, side by side

First the Mustangproject version, using the builder API from the project's own documentation. Note what the last three lines assume: an existing PDF/A file to load, because the exporter embeds XML into a PDF you supply, and validation is a separate concern wired through the validator artifact:

import java.math.BigDecimal;
import java.util.Date;
import org.mustangproject.*;
import org.mustangproject.ZUGFeRD.*;

Invoice invoice = new Invoice()
    .setNumber("RE-2026-001")
    .setIssueDate(new Date()).setDueDate(new Date()).setDeliveryDate(new Date())
    .setSender(new TradeParty(
            "Mustermann Software GmbH", "Hauptstrasse 12", "10115", "Berlin", "DE")
        .addVATID("DE123456789")
        .addBankDetails(new BankDetails("DE89370400440532013000", "COBADEFXXX")))
    .setRecipient(new TradeParty(
            "Beispiel Handel AG", "Marienplatz 8", "80331", "Muenchen", "DE"))
    .addItem(new Item(
        new Product("Softwareentwicklung", "", "HUR", new BigDecimal("19")),
        new BigDecimal("250.00"), new BigDecimal("10")));

// Requires PDF/A input you provide; converts A-1 to A-3 and embeds the XML
IZUGFeRDExporter exporter = new ZUGFeRDExporterFromA1()
    .setProducer("MyApp").setCreator("billing")
    .load("invoice-layout.pdf");
exporter.setTransaction(invoice);
exporter.export("invoice-zugferd.pdf");

The same invoice as one HTTP call with the JDK's own client, no library involved. The API generates the PDF layout, computes totals and the VAT breakdown, produces the conformant PDF/A-3, and validates against the official rule set before returning:

import java.net.URI;
import java.net.http.*;
import java.nio.file.*;

String payload = """
    {
      "invoice": {
        "invoiceNumber": "RE-2026-001",
        "issueDate": "2026-07-29",
        "currency": "EUR",
        "seller": {
          "name": "Mustermann Software GmbH",
          "vatIdentifier": "DE123456789",
          "postalAddress": {
            "line1": "Hauptstrasse 12", "city": "Berlin",
            "postCode": "10115", "country": "DE"
          }
        },
        "buyer": {
          "name": "Beispiel Handel AG",
          "postalAddress": {
            "line1": "Marienplatz 8", "city": "Muenchen",
            "postCode": "80331", "country": "DE"
          }
        },
        "paymentDetails": { "paymentAccountIdentifier": "DE89370400440532013000" },
        "lines": [
          {
            "quantity": 10,
            "unitCode": "HUR",
            "item": { "name": "Softwareentwicklung" },
            "priceDetails": { "netPrice": 250.00 },
            "vatInformation": { "rate": 19 }
          }
        ]
      }
    }
    """;

HttpResponse<byte[]> response = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder()
        .uri(URI.create("https://api.invoicexml.com/v1/create/zugferd"))
        .header("Authorization", "Bearer " + System.getenv("INVOICEXML_API_KEY"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(payload))
        .build(),
    HttpResponse.BodyHandlers.ofByteArray());

Files.write(Path.of("invoice-zugferd.pdf"), response.body());

The difference is not line count; both snippets are short. The difference is what stands behind them. Behind the first: the dependency stack, the PDF/A input requirement, and separate validation. Behind the second: a finished, validated document, and if the request cannot yield a compliant invoice, an HTTP 400 with the violated rules as structured findings instead of a file. To keep your own PDF layout rather than the generated one, the create endpoints accept it and embed the compliant XML into your design.


The migration path in three steps

Step 1: validate your current output. The opening move of the migration costs one HTTP call and no code changes: upload documents your Mustangproject pipeline produces today to POST /v1/validate/zugferd. The endpoint accepts files from any producer, extracts the embedded XML, detects the declared profile, and runs the official XSD and Schematron rules plus PDF/A checks, returning findings with rule ids, plain-language messages, and field paths. The report is your baseline: it shows precisely where your current output stands against the current rule sets and therefore exactly what the switch resolves. Wiring the same call into JUnit keeps that baseline visible for the rest of the migration.

Step 2: swap generation. Replace the Invoice builder chain and the exporter with the JSON request from the mapping table. This is the substantive step, and it is smaller than it looks: the field mapping is mechanical, the API computes totals and the VAT breakdown from your line items, and the PDF/A input problem disappears because the response already is the finished container. Teams that also serve B2G swap in /v1/create/xrechnung for those buyers with the same request model, and the Java guide has the full lifecycle code including Spring Boot patterns.

Step 3: delete the dependency stack. Remove the mustangproject and validator artifacts from your pom, and PDFBox, Saxon-HE, veraPDF, FOP, and their transitive graph leave your build with them. From this point your invoicing code has zero compliance dependencies, nothing for the security scanner to track on this front, and no specification-driven redeploys ahead of it. Incoming documents run through /v1/extract/json for hybrids and /v1/parse/json for the plain supplier PDFs the library never covered, with /v1/extract/attachments unpacking embedded BG-24 documents.

Step 1 is the first move of the migration, not a permanent arrangement: once generation moves in step 2, the same validation endpoint simply becomes your regression check on the API's own output inside CI.


A complete compliance service

What the switch buys, stated as the value proposition it is:

The whole lifecycle behind one integration. Creating ZUGFeRD, Factur-X, XRechnung (both syntaxes), and Peppol BIS UBL from one request model; validating documents from any producer against the official rules; extracting incoming hybrids as JSON; AI parsing for the plain PDFs no library reads; rendering previews; attachment handling. The capability matrix above is not a feature race, but the right column is the complete problem, covered.

The specifications stop being your problem. Current FeRD, KoSIT, and CEN artifacts are live server-side before their effective dates. No release monitoring, no version bumps, no retest-and-redeploy cycle. Your integration is finished the day it works.

Minimal infrastructure, by design. No PDF library, no XSLT processor, no PDF/A tooling, no Schematron artifacts. One HTTP client, which your runtime already ships.

Expertise on call. Deep e-invoicing knowledge with professional support behind the integration, and missing features are integrated on request rather than filed and hoped for.

Processing is stateless throughout: documents are handled in memory and purged when the response ships, nothing is stored or logged, and no invoice data trains any model.


Get started

The fastest way to ground the decision in your own data is step 1 of the migration: validate a few invoices your current pipeline produces and read the report. Create a free InvoiceXML account → and get 100 credits for free, no credit card required.

Runnable Java examples for every operation live in the examples repository.

Related resources:


InvoiceXML is a REST API for European e-invoice compliance covering ZUGFeRD, Factur-X, XRechnung, Peppol UBL, and CII. Stateless processing, GDPR compliant by architecture, and callable from any stack: Java, .NET, Node.js, Python, PHP, Ruby, or anything else with an HTTP client.

Start free today

Ready to automate your invoices?

Validate, convert and embed compliant e-invoices through one API. Start your 30-day free trial. No credit card required.

GDPR Compliant No credit card required Setup in minutes
Peppol UBL
Factur-X
EN 16931
142 / 142 passed
Compliant
PDF/A-3 embedded