PHPackages                             ventnet/xinvoice-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. ventnet/xinvoice-client

ActiveLibrary[Payment Processing](/categories/payments)

ventnet/xinvoice-client
=======================

PHP client for the XInvoice API (api.xinvoice.net): build, generate, validate and retrieve XRechnung (E-Rechnung) and ZUGFeRD e-invoices.

v1.2.0(1mo ago)15MITPHPPHP &gt;=8.1

Since Jun 6Pushed 1mo agoCompare

[ Source](https://github.com/RealZendor/xinvoice)[ Packagist](https://packagist.org/packages/ventnet/xinvoice-client)[ Docs](https://www.xinvoice.net)[ RSS](/packages/ventnet-xinvoice-client/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (10)Versions (6)Used By (0)

XInvoice API Client für PHP
===========================

[](#xinvoice-api-client-für-php)

**Deutsch** | [English](README.en.md)

[![CI](https://github.com/RealZendor/xinvoice/actions/workflows/ci.yml/badge.svg)](https://github.com/RealZendor/xinvoice/actions/workflows/ci.yml)[![Packagist](https://camo.githubusercontent.com/f15ec1635ce4957fafd72b5877426e41924427451328ddeac9affa112796632f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f76656e746e65742f78696e766f6963652d636c69656e742e737667)](https://packagist.org/packages/ventnet/xinvoice-client)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Komfortabler PHP-Client für die [XInvoice API](https://www.xinvoice.net) (`www.xinvoice.net`). Erzeuge, validiere und verwalte **XRechnung** (UBL und CII) sowie **ZUGFeRD / Factur-X**E-Rechnungen direkt aus deiner eigenen Software heraus.

Die Zielgruppe sind Entwickler von Rechnungssoftware, die E-Rechnungen nach **EN 16931** erstellen müssen, ohne XML-, Schematron- und PDF/A-Details selbst implementieren zu wollen.

- Fluent Builder zum schrittweisen Aufbau des Payloads (`addInvoiceItem()`)
- Eingabe wahlweise als Builder, **Array** oder **JSON**
- Framework-unabhängig über PSR-18 / PSR-17 (läuft in Laravel, Symfony, Plain-PHP)
- Typisierte Antwortobjekte, Enums und eine vollständige Exception-Hierarchie
- Polling-Helfer für den asynchronen Standard-Flow

Vollständige API-Referenz:

Installation
------------

[](#installation)

```
composer require ventnet/xinvoice-client
```

Zusätzlich wird eine PSR-18-HTTP-Client- und eine PSR-17-Factory-Implementierung benötigt. Wer noch keine im Projekt hat, installiert z. B.:

```
composer require guzzlehttp/guzzle nyholm/psr7
```

Der Client findet installierte Implementierungen automatisch (via `php-http/discovery`). Alternativ lassen sie sich explizit injizieren.

Voraussetzungen
---------------

[](#voraussetzungen)

- PHP 8.1 oder neuer
- Ein API-Key im Format `xr_.` (Registrierung unter [www.xinvoice.net](https://www.xinvoice.net))
- Ein Konto mit aktivem Billing-Status für produktive Nutzung

Schnellstart
------------

[](#schnellstart)

```
use VentNet\XInvoice\XInvoiceClient;
use VentNet\XInvoice\Builder\InvoiceBuilder;
use VentNet\XInvoice\Builder\PartyBuilder;
use VentNet\XInvoice\Builder\LineBuilder;
use VentNet\XInvoice\Enum\DocumentFormat;

$client = XInvoiceClient::create('xr_your-key-id.your-secret');

$invoice = (new InvoiceBuilder())
    ->documentFormat(DocumentFormat::XRECHNUNG_UBL)
    ->invoiceNumber('RE-2026-001')
    ->issueDate('2026-04-07')
    ->dueDate('2026-04-21')
    ->buyerReference('04011000-12345-03')
    ->currency('EUR')
    ->seller(fn (PartyBuilder $s) => $s
        ->name('Muster GmbH')
        ->vatId('DE123456789')
        ->address('Musterstr. 1', '12345', 'Berlin', 'DE'))
    ->buyer(fn (PartyBuilder $b) => $b
        ->name('Kunde GmbH')
        ->address('Hauptstr. 5', '54321', 'Hamburg', 'DE'))
    ->addInvoiceItem(fn (LineBuilder $l) => $l
        ->name('Webentwicklung')
        ->quantity(10)->unit('HUR')->price(100)->taxRate(19));

$result = $client->generate($invoice, sync: true);

if ($result->isGenerated()) {
    echo $result->xml;
}
```

Den Payload aufbauen
--------------------

[](#den-payload-aufbauen)

Es gibt drei austauschbare und kombinierbare Wege.

### 1. Schrittweise mit dem Builder

[](#1-schrittweise-mit-dem-builder)

```
$invoice = (new InvoiceBuilder())
    ->invoiceNumber('RE-2026-001')
    ->currency('EUR')
    ->addInvoiceItem(fn (LineBuilder $l) => $l->name('Position 1')->quantity(2)->unit('C62')->price(50)->taxRate(19))
    ->addInvoiceItem(['name' => 'Position 2', 'quantity' => 1, 'unit_code' => 'C62', 'price' => 10, 'tax_rate' => 19]);
```

### 2. Aus einem Array

[](#2-aus-einem-array)

```
$invoice = InvoiceBuilder::fromArray([
    'invoice_number' => 'RE-2026-001',
    'currency' => 'EUR',
    'seller' => ['name' => 'Muster GmbH', 'vat_id' => 'DE123456789', /* ... */],
    'buyer' => ['name' => 'Kunde GmbH', /* ... */],
    'items' => [['name' => 'Beratung', 'quantity' => 1, 'unit_code' => 'HUR', 'price' => 100, 'tax_rate' => 19]],
]);

// und danach weiter ergänzen:
$invoice->addInvoiceItem(['name' => 'Zusatz', 'quantity' => 1, 'unit_code' => 'C62', 'price' => 5, 'tax_rate' => 19]);
```

### 3. Aus JSON

[](#3-aus-json)

```
$invoice = InvoiceBuilder::fromJson($jsonString);
```

### Party-Objekte eigenständig erstellen

[](#party-objekte-eigenständig-erstellen)

`PartyBuilder` lässt sich auch unabhängig aufbauen und erst danach zuweisen:

```
$seller = new PartyBuilder();
$seller->name('Muster GmbH');
$seller->vatId('DE123456789');
$seller->address('Musterstr. 1', '12345', 'Berlin', 'DE');
$seller->email('seller@example.com');

$invoice->seller($seller);
```

Arrays, Closures und vorab erstellte Builder sind bei `seller()`, `buyer()` und `addInvoiceItem()` jederzeit mischbar.

### Logo und PDF-Briefkopf (nur ZUGFeRD)

[](#logo-und-pdf-briefkopf-nur-zugferd)

Für das ZUGFeRD-PDF lässt sich entweder ein Logo **oder** ein leeres Briefkopf-PDF (Hintergrund) hinterlegen. Beides schließt sich gegenseitig aus: Ein Briefkopf enthält üblicherweise bereits das Logo, daher hat der Briefkopf Vorrang und ein zusätzlich gesetztes Logo wird ignoriert. Die erzeugte Rechnung wird auf den Briefkopf gesetzt (nur auf der ersten Seite):

```
// Variante A: eigener Briefkopf aus Logo + Daten
$invoice->logoUrl('https://example.com/logo.png');

// Variante B: fertiges Briefkopf-PDF (Logo wird dann ignoriert)
$invoice
    // Briefkopf entweder als URL ...
    ->letterheadUrl('https://example.com/briefkopf.pdf')
    // ... oder als Datei / Base64 (schließt letterheadUrl gegenseitig aus):
    ->letterheadPdfFromFile('/pfad/zu/briefkopf.pdf')
    ->letterheadPdfBase64($base64Pdf)
    // optionale Inhalts-Ränder in mm, damit der Inhalt den Briefkopf nicht überdeckt:
    ->letterheadMargins(top: 45, right: 20, bottom: 30, left: 20);
```

Da der Briefkopf üblicherweise bereits die Angaben des Rechnungserstellers enthält, werden die Seller-Daten im PDF bei verwendetem Briefkopf standardmäßig unterdrückt. Mit `printSellerAddress()` werden sie trotzdem ausgegeben. Das XML bleibt davon unberührt. Das Briefkopf-PDF sollte PDF/A-tauglich sein (eingebettete Schriften, keine Transparenz, nicht verschlüsselt).

```
$invoice->printSellerAddress(); // Seller-Block trotz Briefkopf im PDF ausgeben
```

Rechnungen erzeugen
-------------------

[](#rechnungen-erzeugen)

```
// Asynchron (API-Standard): liefert sofort eine "queued"-Antwort mit Poll-URL
$result = $client->generate($invoice);
$result->isQueued();        // true
$result->invoiceId;         // zum späteren Abrufen / Pollen

// Synchron erzwingen (Header "Prefer: respond-sync")
$result = $client->generate($invoice, sync: true);
```

Eine **synchrone** Anfrage mit blockierenden Validierungsfehlern wirft *keine*Exception, sondern liefert ein `GenerateResult` mit `isFailed() === true`:

```
$result = $client->generate($invoice, sync: true);

if ($result->isFailed()) {
    foreach ($result->validation->errors() as $error) {
        echo "[{$error->code}] {$error->message}\n";
    }
}
```

### Asynchron erzeugen und automatisch pollen

[](#asynchron-erzeugen-und-automatisch-pollen)

```
use VentNet\XInvoice\PollOptions;

$resource = $client->generateAndWait($invoice, new PollOptions(maxAttempts: 30, intervalSeconds: 2));

if ($resource->isGenerated()) {
    $pdf = $client->downloadPdf($resource->invoiceId); // nur bei ZUGFeRD
}
```

Validieren (ohne Speichern)
---------------------------

[](#validieren-ohne-speichern)

```
$client->validate($invoice);                    // JSON-Payload
$client->validateXml($xmlString);               // rohes XML
$client->validatePdf($pdfBinary);               // rohes ZUGFeRD-PDF
$client->validatePdfBase64($base64String);      // ZUGFeRD-PDF als Base64

$response = $client->validate($invoice);
$response->isValid();
$response->validation()->errors();
```

Rechnungen abrufen und auflisten
--------------------------------

[](#rechnungen-abrufen-und-auflisten)

```
use VentNet\XInvoice\Query\ListInvoicesQuery;
use VentNet\XInvoice\Enum\InvoiceStatus;

$resource = $client->getInvoice($invoiceId);
$resource = $client->getInvoice($invoiceId, includePdf: true);

$list = $client->listInvoices(
    ListInvoicesQuery::create()
        ->status(InvoiceStatus::GENERATED)
        ->createdFrom('2026-04-01')
        ->perPage(50)
);

foreach ($list as $summary) {
    echo $summary->invoiceNumber . ' – ' . $summary->status->value . PHP_EOL;
}

$list->meta->total;
$list->meta->hasMorePages();

// PDF-Bytes herunterladen
file_put_contents('invoice.pdf', $client->downloadPdf($invoiceId));
```

Systemendpunkte
---------------

[](#systemendpunkte)

```
$client->ping();        // bool – öffentliche Liveness-Prüfung
$client->readiness();   // ReadinessResult – Validierungs-Runtime bereit?

```

Fehlerbehandlung
----------------

[](#fehlerbehandlung)

Alle Fehler implementieren `VentNet\XInvoice\Exception\XInvoiceException`, sodass sie sich gemeinsam fangen lassen.

HTTPException401`AuthenticationException`402`PaymentRequiredException`404`NotFoundException`422`RequestValidationException` (mit `getErrors()`)429`RateLimitException` (mit `getRetryAfter()`)5xx`ServerException`Netzwerk`TransportException````
use VentNet\XInvoice\Exception\RequestValidationException;
use VentNet\XInvoice\Exception\RateLimitException;
use VentNet\XInvoice\Exception\XInvoiceException;

try {
    $client->generate($invoice);
} catch (RequestValidationException $e) {
    foreach ($e->getErrors() as $field => $messages) {
        // Feldfehler verarbeiten
    }
} catch (RateLimitException $e) {
    sleep($e->getRetryAfter() ?? 5);
} catch (XInvoiceException $e) {
    // alle übrigen Client-Fehler
}
```

Konfiguration
-------------

[](#konfiguration)

```
use VentNet\XInvoice\ClientConfig;
use VentNet\XInvoice\Enum\DocumentFormat;

$config = new ClientConfig(
    baseUrl: 'https://api.xinvoice.net/v1',     // z. B. für lokale Tests überschreibbar
    userAgent: 'meine-rechnungssoftware/2.0',
    defaultDocumentFormat: DocumentFormat::ZUGFERD,
);

$client = XInvoiceClient::create('xr_keyId.secret', $config);
```

Eigene PSR-18/PSR-17-Implementierungen injizieren:

```
$client = new XInvoiceClient(
    apiKey: 'xr_keyId.secret',
    config: new ClientConfig(),
    httpClient: $myPsr18Client,
    requestFactory: $myPsr17Factory,
    streamFactory: $myPsr17Factory,
);
```

Beispiele
---------

[](#beispiele)

Lauffähige Skripte liegen im Ordner [`examples/`](examples/).

Entwicklung
-----------

[](#entwicklung)

```
composer install
composer test     # PHPUnit
composer stan     # PHPStan (level max)
composer cs-fix   # PHP-CS-Fixer
```

Lizenz
------

[](#lizenz)

MIT – siehe [LICENSE](LICENSE).

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

47d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6a8b2f54c40d36c96d78006994aa0affbfdeb1a1a152cb3fee00db13cd72ed76?d=identicon)[RealZendor](/maintainers/RealZendor)

---

Top Contributors

[![RealZendor](https://avatars.githubusercontent.com/u/58033568?v=4)](https://github.com/RealZendor "RealZendor (5 commits)")

---

Tags

invoiceZUGFeRDfactur-xxrechnungapi clientE-InvoiceEN16931e-rechnung

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ventnet-xinvoice-client/health.svg)

```
[![Health](https://phpackages.com/badges/ventnet-xinvoice-client/health.svg)](https://phpackages.com/packages/ventnet-xinvoice-client)
```

###  Alternatives

[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

36789.4k2](/packages/telnyx-telnyx-php)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

85036.3k](/packages/flow-php-flow)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k16](/packages/tempest-framework)[chargebee/chargebee-php

ChargeBee API client implementation for PHP

758.5M9](/packages/chargebee-chargebee-php)[getbrevo/brevo-php

Official Brevo provided RESTFul API V3 php library

1003.9M50](/packages/getbrevo-brevo-php)[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

185702.8k44](/packages/laudis-neo4j-php-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
