Logo of the Mustang project

PDF invoice metadata

The Mustang project is a java library to read and write ZUGFeRD meta data inside your invoice PDFs

Get the docs »


There is another Mustang project on car parts and one on youth and horses.

This Mustang project is a Java im- and exporter library for the ZUGFeRD standard. ZUGFeRD, in version 2 also called Factur-X, is a electronic invoice meta data standard, see ferd-net.

More precisely, this library is using Apache PDFBox to support the "Extended" profile of version 1 and 2 (public preview) of the ZUGFeRD/Factur-X standard. It was developed in the context of usegroup's Gnuaccounting open source accounting application.

The name refers to Mustangs, which are often considered as wild and free horses. The german name of the ZUGFeRD standard resembles a Zugpferd, a drafting horse. This is why the Mustang as a free horse gave the free ZUGFeRD implementation it's name.

Mustangproject 1.5.1 for ZUGFeRD 1.0 and ZF 2 public review was released on 2018-01-13.


The files are subject to the Apache license and can therefore be used for free in commercial and noncommercial projects.

Projects using it

Using it



Apart from the

Please let me know via the mailing list if I'm missing something or I am in error.


The source code is hosted on GitHub.

Both the english and the german documentation on importing and exporting ZUGFeRD data with the Mustangproject, including samples, are available in the GitHub repository.

Screenshot of Acrobat Adobe PDF Reader showing a ZUGFeRD invoice with open file attachments tab At the right you see a sample PDF containing ZUGFeRD metadata generated with the Mustang library. If you open it in Adobe Acrobat Reader just click on the paperclip symbol to see the embedded ZUGFeRD XML structure.

Unless you used a corrupted input PDF, the created PDF/A-3 validate against 3-Heights™ PDF Validator Online Tool. If you embed custom ZUGFeRD XML please make sure that your ZUGFeRD file additionally validates against the FERDmc checker powered by intrasys. Version 1 files can also be validated against the schematron (ZUGFeRD_1p0.scmt in the official download),

Due to the early stage of status of ZUGFeRD 2.0 and therefore lack of validators and schematron merely a smoke check vis a vis the schema files seems to be possible at this stage (2017-11-30). Please feel free to manually validate the according ZUGFeRD 2.0 (public review) sample file and it's embedded XML structure and report any errors you encounter.

Internal architecture

  1. We base on a PDF/A-1a file as input with the human readable representation of the invoice. PDF/A is a substandard of PDF to allow long term archival of the files which are, unlike PDF, therefore required to include and not to link to external resources like fonts. This base file can be generated using e.g. Apache OpenOffice.org (using UNO or e.g. NOA-libre) or directly using PDFBox as in this sample. Just make sure the input PDF file is valid PDF/A-1, e.g. using the 3-Heights™ PDF Validator Online Tool.
  2. The three conformance levels of PDF, PDF/A-3a, A-3u and A-3b, more or less refer to completely compliant documents, documents which at least preserve unicode and documents which preserve at least the optical representation. We use Apache PDFBox to change the input PDF/A-1a file to a PDF/A-3u file. If it were tagged PDF we could even export to PDF/A-3a but usually we can not guarantee that the source file is completely tagged, i.e. semantically useful for e.g. blind users.
  3. Then we embed a XML file, conforming to the according schema delivered with ZUGFeRD.
  4. And add information in the RDF-metadata part of the PDF document, indicating that the embedded ZUGFeRD-invoice.xml is indeed a ZUGFeRD invoice. This also requires us to add according PDF/A schema extensions.
  5. The functionality to migrate from ZUGFeRD 1 to 2 (part 1 public review) is based on a XSLT transformation.


After downloading Mustang, besides integrating into your software you can also use it on the command line:

Extract XML

➜ target git:(master) ✗ java -jar mustang-1.5.0.jar -e

            Source PDF (default: invoice.pdf):/Users/jstaerk/Desktop/mustangZF1test.pdf
            ZUGFeRD XML (default: ZUGFeRD-invoice.xml):
            Written to ZUGFeRD-invoice.xml

Migrating ZUGFeRD 1 to 2

java -jar mustang-1.5.0.jar -u

            ZUGFeRD 1.0 XML source (default: ZUGFeRD-invoice.xml):
            ZUGFeRD 2.0 XML target (default: factur-x.xml):
            Written to factur-x.xml

To migrate XML from ZF1 to Version 2 Mustangproject internally uses a self-written (read: incomplete) XSLT-Transformation. Corrections and amendments are much appreciated.

Combining PDF and XML

In this case the source PDF has to be a PDF/A-1 like our "blanko"

java -jar mustang-1.5.0.jar -c

            Source PDF (default: invoice.pdf):
            ZUGFeRD XML (default: ZUGFeRD-invoice.xml):
            Ouput PDF (default: invoice.ZUGFeRD.pdf):
            ZUGFeRD version (1 or 2) (default: 1):
            ZUGFeRD profile b)asic, c)omfort or e)xtended (default: e):
            Written to invoice.ZUGFeRD.pdf

Migration PDF/A-1 to PDF/A-3

java -jar mustang-1.5.0.jar -a

Migrates a PDF/A-1 into a PDF/A-3 file without adding ZUGFeRD metadata hinzuzufügen. The same contents will be labelled the new version (which is valid because the format is backward-compatible), additional features like the PDF/A-2 JPG2000-compression of images will not be used.


The original purpose for the command line tool was finding out, how many ZUGFeRD invoices already existed in a directory structure of PDFs. Use

java -jar mustang-1.5.0.jar -d <Directory name> E.g. java -jar mustang-1.5.0.jar -d /tmp/XMLExamples
            Files: 145 Dirs: 15 PDF: 18 ZUGFeRD: 14

Each dot is a checked file. The software works recursively, in this example 18 PDF files were found in 15 directories. 14 of those 18 files were identified as ZUGFeRD 1 or 2. Usually only files ending in .pdf, .PDF etc. are checked. By additionally specifying -i it is possible to check independently from file name extension.

java -jar mustang-1.5.0.jar -l

With -l it is possible to pass a list of files to be checked for ZUGFeRDIty via standard input. A empty last line starts the check. Example:

java -jar mustang-1.5.0.jar -l


            Files: 19 Dirs: 0 PDF: 19 ZUGFeRD: 15


Mailing list and credits

At https://groups.google.com/forum/?hl=de#!forum/zugferd



For multiplier inquiries or legal issues please contact Jochen Stärk at jstaerk [at] zugferd.org or postal:

usegroup c/o Jochen Stärk
Huswertstr. 14
60435 Frankfurt