PHP code example of ventnet / xinvoice-client

1. Go to this page and download the library: Download ventnet/xinvoice-client library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ventnet / xinvoice-client example snippets


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;
}

$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]);

$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]);

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

$seller = new PartyBuilder();
$seller->name('Muster GmbH');
$seller->vatId('DE123456789');
$seller->address('Musterstr. 1', '12345', 'Berlin', 'DE');
$seller->email('[email protected]');

$invoice->seller($seller);

// 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);

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

use VentNet\XInvoice\Builder\AllowanceBuilder;

$invoice
    ->addAllowance(fn (AllowanceBuilder $a) => $a
        ->reason('Nachlass')
        ->amount(100)
        ->taxRate(19)
        ->baseAmount(1000)
        ->percentage(10))
    ->prepaidAmount(500);

use VentNet\XInvoice\Enum\VatCategoryCode;

$invoice
    ->taxCategory(VatCategoryCode::REVERSE_CHARGE)
    ->taxExemptionReason('Steuerschuldnerschaft des Leistungsempfängers')
    ->taxExemptionReasonCode('VATEX-EU-AE');

use VentNet\XInvoice\Builder\PrecedingInvoiceReferenceBuilder;
use VentNet\XInvoice\Enum\InvoiceTypeCode;

$invoice
    ->invoiceTypeCode(InvoiceTypeCode::CORRECTED_INVOICE)
    ->addPrecedingInvoiceReference(
        fn (PrecedingInvoiceReferenceBuilder $reference) => $reference
            ->invoiceNumber('RE-2026-001')
            ->issueDate('2026-04-07'),
    )
    ->precedingInvoiceReference('RE-2025-100');

'preceding_invoice_references' => [
    ['invoice_number' => 'RE-2026-001', 'issue_date' => '2026-04-07'],
    ['invoice_number' => 'RE-2025-100'],
],

// 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);

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

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

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
}

$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();

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

$resource = $client->getInvoice($invoiceId);
$resource = $client->getInvoice($invoiceId,  ($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));

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

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
}

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);

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