Search by

invoapi / invoapi-php

invoapi

PHP client for the invoapi.de e-invoicing API: create and validate XRechnung, ZUGFeRD / Factur-X, EN 16931, UBL, CII and Peppol invoices.

v0.1.0 2026-10-29 22:09 UTC

This package is auto-updated.

Last update: 2026-10-30 17:32:32 UTC


README

PHP-Client für die invoapi.de E-Rechnungs-API: XRechnung, ZUGFeRD / Factur-X, EN 16931, UBL, CII und Peppol erzeugen, gegen die offiziellen Regelwerke prüfen, umwandeln und auslesen.

  • PHP 8.1 oder neuer, nur ext-curl und ext-json, keine weiteren Abhängigkeiten
  • Jede erzeugte Rechnung wird mit dem offiziellen KoSIT-Validator geprüft
  • Automatische Wiederholung bei Tempolimit (429) und kurzzeitigen Ausfällen (503)

English: PHP client for the invoapi.de e-invoicing API. Create XRechnung, ZUGFeRD / Factur-X, EN 16931, UBL, CII and Peppol invoices, validate them against the official rule sets (KoSIT), convert and parse them. PHP 8.1+, only ext-curl and ext-json. Install with composer require invoapi/invoapi-php; the examples below work the same in any language, see the API documentation.

Installation

composer require invoapi/invoapi-php

Den API-Schlüssel finden Sie im Dashboard unter API-Schlüssel.

Schnellstart: XRechnung erzeugen

<?php
require 'vendor/autoload.php';

$invoapi = new Invoapi\Client(getenv('INVOAPI_API_KEY'));

$rechnung = $invoapi->generate([
    'invoice_number'  => 'RE-2026-0001',
    'issue_date'      => '2026-10-28',
    'due_date'        => '2026-11-27',
    'currency'        => 'EUR',
    'buyer_reference' => '04011000-12345-34',   // Leitweg-ID, Pflicht bei XRechnung an Behörden
    'seller' => [
        'name' => 'Muster GmbH', 'street' => 'Musterstraße 1', 'postal_code' => '10115',
        'city' => 'Berlin', 'country_code' => 'DE', 'vat_id' => 'DE123456789',
        'email' => 'rechnung@muster.de', 'phone' => '+49 30 1234567',
    ],
    'buyer' => [
        'name' => 'Beispiel GmbH', 'street' => 'Teststraße 10', 'postal_code' => '20095',
        'city' => 'Hamburg', 'country_code' => 'DE', 'email' => 'kreditoren@beispiel.de',
    ],
    'items' => [
        ['name' => 'Beratung', 'quantity' => 8, 'unit' => 'HUR', 'unit_price' => 145, 'vat_rate' => 19],
    ],
    'payment' => ['means_code' => '58', 'iban' => 'DE02120300000000202051'],
], format: 'xrechnung');

if ($rechnung->isValid()) {
    $rechnung->saveTo($rechnung->filename());      // RE-2026-0001.xml
    echo $rechnung->totals()['payable'];           // "1380.40"
}

Alle Felder der Rechnung beschreibt die API-Dokumentation.

ZUGFeRD-PDF

$pdf = $invoapi->generate($daten, format: 'zugferd', output: 'pdf', profile: 'en16931');
$pdf->saveTo('RE-2026-0001.pdf');   // PDF/A-3 mit eingebettetem XML

Eingehende E-Rechnung prüfen

$bericht = $invoapi->validate(file_get_contents('eingang.xml'));   // XML oder ZUGFeRD-PDF

if (!$bericht->isValid()) {
    foreach ($bericht->errors() as $fehler) {
        echo "{$fehler['rule']}: {$fehler['message']}\n";       // z. B. "BR-DE-15: Leitweg-ID fehlt"
    }
}

isValid() ist nur dann true, wenn ein offizielles Regelwerk tatsächlich gelaufen ist.

Auslesen, erkennen, umwandeln, rechnen

$daten  = $invoapi->parse($xmlOderPdf);          // Rechnung als Array: Verkäufer, Käufer, Positionen, Summen
$format = $invoapi->detect($xmlOderPdf);         // ['format' => 'xrechnung', 'syntax' => 'ubl', ...]
$cii    = $invoapi->convert($ublXml, 'xml', format: 'xrechnung', syntax: 'cii');
$pdf    = $invoapi->convert($ublXml, 'pdf', format: 'zugferd');   // XRechnung → ZUGFeRD-PDF
$html   = $invoapi->render($xmlOderPdf, 'html');                 // lesbare Ansicht für Menschen
$summen = $invoapi->calculate($daten)['totals'];                  // kostenlos, zählt nicht aufs Kontingent

Fehlerbehandlung

Jede Ablehnung wirft eine Ausnahme mit der verständlichen Meldung der API:

Ausnahme Wann Was tun
Invoapi\Exception\InvalidRequestException Rechnung oder Dokument fehlerhaft (400/422) getDetails() nennt die Felder
Invoapi\Exception\AuthenticationException Schlüssel falsch, E-Mail unbestätigt, Konto gesperrt Schlüssel im Dashboard prüfen
Invoapi\Exception\QuotaExhaustedException Gratis-Kontingent aufgebraucht (402) Tarif wählen: invoapi.de/preise
Invoapi\Exception\RateLimitException Zu viele Aufrufe (429), nach den Wiederholungen getRetryAfter() Sekunden warten
Invoapi\Exception\ServiceUnavailableException Dienst kurz nicht erreichbar (5xx) später erneut versuchen
Invoapi\Exception\ConnectionException Keine Verbindung (DNS, TLS, Timeout) Netzwerk prüfen

Alle erben von Invoapi\Exception\InvoapiException mit getErrorCode() und getRequestId(). Die Request-ID hilft uns bei Support-Anfragen.

try {
    $rechnung = $invoapi->generate($daten);
} catch (Invoapi\Exception\InvalidRequestException $e) {
    echo $e->getMessage();
} catch (Invoapi\Exception\InvoapiException $e) {
    error_log("invoapi: {$e->getMessage()} ({$e->getRequestId()})");
}

Optionen

$invoapi = new Invoapi\Client($apiKey, [
    'timeout'     => 90,    // Sekunden pro Anfrage
    'max_retries' => 2,     // Wiederholungen bei 429/503, 0 schaltet sie ab
]);

Tests

composer install
vendor/bin/phpunit --testsuite unit                                    # ohne Netzwerk
INVOAPI_API_KEY=inv_… vendor/bin/phpunit --testsuite integration       # gegen die echte API, verbraucht Kontingent

Lizenz

MIT