Documentation

VAMPIRE PHP – documentation

VAMPIRE PHP checks e-invoices directly inside your PHP process. It needs no Java, starts no other program and opens no network connection, so the invoice never leaves your server. This page shows you how to install VAMPIRE PHP and check your first invoice.


What matters

To our knowledge, VAMPIRE PHP is the only tool that runs the official validation rules for e-invoices completely in pure PHP. VAMPIRE JS brings the same rule packages to pure JavaScript. Neither needs Java or an extra process, and the invoice never leaves your system.

Evidence: 220 of 220 invoices for which VAMPIRE and the official KoSIT validator reached the same result, measured on October 9, 2026.


97.7 % / 100 %

of the invoices for which VAMPIRE PHP and the official KoSIT validator fired exactly the same rules, before and after allowing for one explained difference in the version of the rules

measured on October 7, 2026

220 of 220

invoices for which VAMPIRE and the official KoSIT validator reached the same result

measured on October 9, 2026

2,544

comparisons of VAMPIRE JS with VAMPIRE PHP, each one rule set with one invoice, all without a single difference

measured on October 9, 2026

253 of 253

invoices for which VAMPIRE JS and VAMPIRE PHP produced exactly the same validation report

measured on October 9, 2026


What you need and how to install VAMPIRE PHP

VAMPIRE PHP is a validator for e-invoices written in pure PHP. It needs PHP 8.2 or newer with the extensions dom, libxml and bcmath, and it has no other runtime dependencies. This means it also runs on ordinary shared hosting. VAMPIRE PHP is free software under the GPL-2.0-or-later. You install it from Packagist with composer require invoicepress/vampire-php; the individual steps are in the Composer guide.


Your first check in five lines

The following file checks one invoice. It prints "accepted" if the invoice is accepted and "rejected" if it is rejected. The file runs exactly as shown here. Call it in your project folder with php check.php invoice.xml.

<?php
// SPDX-License-Identifier: MIT
// Checks one e-invoice with VAMPIRE PHP:  php check.php invoice.xml
// A command-line script: it reads the file name from the command line and refuses to run in a web server.
if ( PHP_SAPI !== 'cli' ) exit( 1 );

require __DIR__ . '/vendor/autoload.php';
$vampire  = __DIR__ . '/vendor/invoicepress/vampire-php';
$resolver = EinvoiceValidator\Pipeline\ScenarioResolver::fromJsonFile( $vampire . '/rulesets/scenarios.json' );
$result   = ( new EinvoiceValidator\Validator( scenarioResolver: $resolver, baseDir: $vampire ) )->validateFile( $argv[1] );
printf( "%s: %s\n", $argv[1], $result->isAccepted() ? 'accepted' : 'rejected' );

The file scenarios.json holds the matching rules. It decides which schema and which rule sets an invoice gets. A rule set holds the validation rules of one format in one version, for example the rules of XRechnung 3.0.2. baseDir is the folder that the paths in this file are resolved against; that is the package folder.


Printing findings and writing reports

The second example prints every finding one by one. It then writes three reports, each for a different purpose: the JSON report for your own software, a printable HTML page for people, and the report in the format of the KoSIT validator for tools that already read that format. With ruleReport: true, the JSON report also contains the positive validation report, which lists every checked rule with its result on a line of its own.

JSON report
for your own software, optionally with the positive validation report
HTML page
printable, for reading and filing
KoSIT format
for tools that already read this report
One check, three reports: for your software, for printing, and in the format of the KoSIT validator.
<?php
// SPDX-License-Identifier: MIT
// Checks one e-invoice with VAMPIRE PHP, prints the findings and writes the reports:  php report.php invoice.xml
//   report.json        the JSON report, with the positive validation report ( every rule with its result )
//   report.html        a printable page
//   report-kosit.xml   the report in the format of the KoSIT validator
// A command-line script: it reads the file name from the command line and refuses to run in a web server.
if ( PHP_SAPI !== 'cli' ) exit( 1 );

require __DIR__ . '/vendor/autoload.php';

use EinvoiceValidator\Pipeline\ScenarioResolver;
use EinvoiceValidator\Report\{ HtmlReport, JsonReport, KositXmlReport };
use EinvoiceValidator\Validator;

$vampire   = __DIR__ . '/vendor/invoicepress/vampire-php';
$resolver  = ScenarioResolver::fromJsonFile( $vampire . '/rulesets/scenarios.json' );
$validator = new Validator( scenarioResolver: $resolver, baseDir: $vampire, ruleReport: true );
$result    = $validator->validateFile( $argv[1] );

foreach ( $result->messages() as $message ) {
	printf( "%-12s %-14s %s\n", $message->flag->value, $message->ruleId ?? '-', trim( $message->text ) );
}

file_put_contents( 'report.json', ( new JsonReport() )->toJson( $result ) );
file_put_contents( 'report.html', ( new HtmlReport() )->render( $result ) );
file_put_contents( 'report-kosit.xml', ( new KositXmlReport() )->render( $result, (string) file_get_contents( $argv[1] ) ) );

echo $result->isAccepted() ? "accepted\n" : "rejected\n";
exit( $result->isAccepted() ? 0 : 1 );

⚠️ Read the result from isAccepted(), not from the number of errors. The result says whether the invoice is accepted or rejected. The number of errors alone can be misleading in two cases: a rule set may mark a warning as blocking, and an invoice that VAMPIRE could not match to any rule set has no rule findings at all, yet it is still not accepted.


How to check on the command line

vendor/bin/einvoice-validator validate invoice.xml
vendor/bin/einvoice-validator validate invoice.xml --format=json --rule-report
vendor/bin/einvoice-validator validate invoice.xml --matrix
vendor/bin/einvoice-validator ruleset:list
vendor/bin/einvoice-validator selftest

The exit code is 0 for an accepted invoice and 1 for a rejected one. For an invalid call it is 2. This makes it easy to use the check in scripts and pipelines.

With the option --cascade, VAMPIRE checks a ZUGFeRD or Factur-X invoice first against the rules of the newest version and, if it is rejected there, against the rules of the next older one. It stops at the first version under whose rules the invoice is accepted. If no version accepts the invoice, VAMPIRE shows the report of the newest version, because the invoice is then faulty under every version, and the newest one is the authoritative one. The option --matrix, by contrast, checks every version and prints a table with one row per version, so you see the result of every single version.


How to check invoices from horstoeko/zugferd

Do you create your invoices with horstoeko/zugferd or horstoeko/invoicesuite? Then VAMPIRE PHP can check them in the same process, without going through a file. You simply pass the finished document to the validator:

$result = $validator->validateDom( $document->getContentAsDomDocument() );

$document is the document you built with ZugferdDocumentBuilder. $validator is the validator from the first example. If you have the XML as a string, use validateString() instead. You need no extra package for this, because you simply call VAMPIRE PHP in the usual way.


How to get new rule releases

New rule releases arrive as a new version of the package, and the command composer update invoicepress/vampire-php fetches them. The rule packages are free, and there is no subscription for them.

Same result as the KoSIT validator220 of 220
Exactly the same rules fired215 of 220
Comparison with the official KoSIT validator on the 220 invoices both could match to a rule set: same result measured on October 9, 2026, same rules measured with VAMPIRE PHP on October 7, 2026.

How we measured this is described in the section "How it was measured" at the end of this page. Install VAMPIRE PHP for free with Composer now and check your first invoice.


How it was measured

  • 220 of 220 invoices for which VAMPIRE and the official KoSIT validator reached the same result (measured on October 9, 2026): We checked 253 test invoices with VAMPIRE and with the official KoSIT validator. Both could match 220 of them to a rule set, and for all 220 both reached the same result, that is accepted or rejected. For 215 of these 220 invoices, exactly the same rules fired as well; for the other five, the difference comes from the version of the EN 16931 rules for CII, because the KoSIT validator ships version 1.3.15 and VAMPIRE ships version 1.3.16. Neither validator could match the remaining 33 invoices to a rule set. Date of the measurement: October 9, 2026.
  • 97.7 % / 100 % of the invoices for which VAMPIRE PHP and the official KoSIT validator fired exactly the same rules, before and after allowing for one explained difference in the version of the rules (measured on October 7, 2026): We checked 220 invoices that VAMPIRE could match to a rule set with VAMPIRE PHP and with the official KoSIT validator and compared which rules fire. For 215 of the 220 invoices, exactly the same rules fired, which is 97.7 percent. The other five are XRechnung invoices in CII for which VAMPIRE applies the newer version 1.3.16 of the EN 16931 rules while the KoSIT validator applies version 1.3.15; once this known difference is taken into account, 100 percent match. We give both figures because the first alone would hide the reason and the second alone would look too good.
  • 2,544 comparisons of VAMPIRE JS with VAMPIRE PHP, each one rule set with one invoice, all without a single difference (measured on October 9, 2026): Every rule set ran in VAMPIRE JS and in VAMPIRE PHP over all invoices of its format. For each pair of rule set and invoice, we compared which rules fired. This gave 2,544 comparisons with 0 differences and 0 aborts.
  • 253 of 253 invoices for which VAMPIRE JS and VAMPIRE PHP produced exactly the same validation report (measured on October 9, 2026): We checked 253 invoices with VAMPIRE JS and with VAMPIRE PHP and compared the two reports for each invoice. We compared the detected rule set, the result (accepted or rejected), the results of the four check steps (well-formedness, schema, syntax rules, business rules), all 184 findings with text and location, and the report in the format of the KoSIT validator byte for byte. The report was the same for all 253 invoices. Of these invoices, 144 come from our own test corpus and 109 from the test suite of XRechnung 3.0.2.

VAMPIRE PHP free, VAMPIRE JS in the shop.

VAMPIRE PHP and all rule packages are free and available on GitHub and Packagist. You can buy VAMPIRE JS in the shop on invoicePress.de.