API-Dokumentation
Mit der Schnittstelle übergibt Ihr System eine Rechnung an Rechnungswerk. Rechnungswerk vergibt die Rechnungsnummer, erzeugt ZUGFeRD-PDF und XRechnung, prüft beide und versendet sie auf Wunsch per E-Mail.
- Basisadresse
https://api.erechnung2027.entgema.com/v1- Alternativ
https://erechnung2027.entgema.com/api/v1- Anmeldung
Authorization: Bearer <Schlüssel>- Format
- JSON, UTF-8
Schnellstart
Schlüssel besorgen
Sie erhalten Ihren API-Schlüssel vom Betreiber. Er beginnt mit
rw_und wird nur einmal angezeigt.Rechnung als JSON aufbauen
Kunde, Positionen und Leistungszeitraum – siehe Rechnung einliefern.
Einliefern
curl -X POST https://api.erechnung2027.entgema.com/v1/submit \ -H "Authorization: Bearer rw_IHR_SCHLUESSEL" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: auftrag-4711" \ -d @rechnung.json
Antwort auswerten
Sie erhalten Rechnungsnummer, Beträge, Adressen der Dateien und den Stand des Versands.
Zugang und Schlüssel
Jeder Aufruf trägt den Schlüssel im Kopf Authorization: Bearer rw_…. Ein Schlüssel hat eine oder mehrere Berechtigungen:
| Berechtigung | Erlaubt |
|---|---|
read | Lesen von Rechnungen, Kunden und Dateien (immer enthalten) |
write | Kunden und Rechnungsentwürfe anlegen |
issue | Rechnungen verbindlich ausstellen und stornieren |
email.send | E-Mails versenden |
Behandeln Sie den Schlüssel wie ein Passwort: nur serverseitig verwenden, nie in einer App oder im Browser ausliefern. Bei Verdacht auf Missbrauch lässt ihn der Betreiber sofort widerrufen.
Grundregeln
- Wiederholungen sind sicher
- Jeder
POSTbraucht den KopfIdempotency-Key(8–128 Zeichen aus Buchstaben, Ziffern und_ . : -). Derselbe Schlüssel mit demselben Inhalt liefert das ursprüngliche Ergebnis und legt nichts doppelt an. Verwenden Sie z. B. Ihre Auftragsnummer. - Beträge als Text
- Mengen und Preise als Zeichenkette mit Punkt senden:
"120.00","2.5". Ganze Zahlen werden angenommen, JSON-Gleitkommazahlen abgelehnt – so entstehen keine Rundungsfehler. - Rechnen übernimmt Rechnungswerk
- Sie senden Menge, Nettopreis, Rabatt und Steuersatz. Netto, Umsatzsteuer und Brutto berechnet der Server und gibt sie zurück.
- Datum
- Immer
JJJJ-MM-TT. - Umfang
- Kunden in Deutschland, Währung Euro, Regelbesteuerung mit 19 % oder 7 %.
- Ausgestellt heißt unveränderlich
- Eine ausgestellte Rechnung lässt sich nicht mehr ändern, nur stornieren.
Rechnung einliefern
POSThttps://api.erechnung2027.entgema.com/v1/submit
Ein Aufruf erledigt alles: Kunde finden oder anlegen, Rechnung anlegen und ausstellen, Dateien erzeugen, prüfen und – mit "send": true – versenden. Benötigt write, zum Ausstellen issue, zum Senden email.send.
Anfrage
{
"customer": {
"name": "Beispielkunde GmbH",
"street": "Testweg 5",
"postcode": "20095",
"city": "Hamburg",
"email": "buchhaltung@beispielkunde.de",
"buyer_reference": "AUFTRAG-4711"
},
"invoice": {
"issue_date": "2026-10-04",
"service_start": "2026-09-01",
"service_end": "2026-09-30",
"lines": [
{"name": "Beratung", "description": "Analyse und Konzept", "quantity": "2.5", "price": "120.00", "unit": "HUR", "vat": "19"}
]
},
"send": true
}
| Feld | Pflicht | Bedeutung |
|---|---|---|
customer_id | eines von beiden | Nummer oder UUID eines vorhandenen Kunden |
customer | eines von beiden | Kundendaten: name, street, postcode, city, email (Pflicht), dazu vat_id, contact, phone, buyer_reference. Ein Kunde mit gleicher E-Mail und gleichem Namen wird wiederverwendet. |
invoice.lines | ja | Positionen, mindestens eine – siehe unten |
invoice.issue_date | nein | Rechnungsdatum, Standard: heute |
invoice.service_start, service_end | nein | Leistungszeitraum, Standard: Rechnungsdatum |
invoice.due_date | nein | Fälligkeit, Standard: Rechnungsdatum + 14 Tage |
invoice.buyer_reference | siehe Text | Käuferreferenz bzw. Leitweg-ID. Fehlt sie hier und beim Kunden, kann die Rechnung nicht ausgestellt werden. |
invoice.terms, invoice.note | nein | Zahlungsbedingungen, Hinweistext |
issue | nein | Standard true. Mit false entsteht nur ein Entwurf. |
send | nein | Standard false. Mit true wird sofort versendet. |
email | nein | Abweichend von der Vorlage: recipient, subject, body, selection (["zugferd","xrechnung"]) |
Position
| Feld | Pflicht | Bedeutung |
|---|---|---|
name | ja | Bezeichnung, höchstens 200 Zeichen |
description | nein | Beschreibung, Absätze bleiben erhalten |
quantity | nein | Menge, bis vier Nachkommastellen, Standard "1" |
price | ja | Einzelpreis netto in Euro, bis vier Nachkommastellen |
discount | nein | Rabatt in Prozent, 0 bis 100 |
unit | nein | C62 Stück (Standard), HUR Stunde, DAY Tag, MON Monat, MTR Meter, KGM Kilogramm, LTR Liter |
vat | nein | "19" (Standard), "7" oder "0" (steuerfrei). Bei "0" braucht die Rechnung das Feld exemption_reason, z. B. „Steuerfrei nach § 4 Nr. 21 UStG“. Ist der Betreiber Kleinunternehmer (§ 19 UStG), wird jede Position ohne Umsatzsteuer berechnet. |
Antwort 201
{
"invoice": {
"id": 12, "uuid": "9f1c…", "number": "RE-2026-000012", "status": "issued",
"issue_date": "2026-10-04", "due_date": "2026-10-18",
"net": "300.00", "tax": "57.00", "gross": "357.00", "currency": "EUR",
"payment_status": "unpaid", "paid": "0.00",
"url": "https://api.erechnung2027.entgema.com/v1/invoices/12"
},
"files": {
"zugferd": {"url": "https://api.erechnung2027.entgema.com/v1/invoices/12/files/zugferd", "sha256": "…", "size": 48211},
"xrechnung": {"url": "https://api.erechnung2027.entgema.com/v1/invoices/12/files/xrechnung", "sha256": "…", "size": 6120},
"zugferd_xml": {"url": "https://api.erechnung2027.entgema.com/v1/invoices/12/files/zugferd_xml", "sha256": "…", "size": 5980}
},
"validation": {"status": "unvalidated", "internal_passed": true, "message": "Interne Prüfung bestanden: …", "errors": []},
"sendable": true,
"mail_mode": "smtp",
"customer": {"id": 3, "created": true},
"dispatch": {
"status": "sent", "email_id": 20, "recipient": "buchhaltung@beispielkunde.de",
"subject": "Ihre Rechnung RE-2026-000012", "sent_at": "2026-10-04T00:50:00+02:00",
"already_sent": false, "reason": null
}
}
Stand des Versands
dispatch.status | Bedeutung |
|---|---|
sent | Der Mailserver hat die Nachricht angenommen. Das ist keine Zustellbestätigung. |
test_mode | Testmodus des Betreibers: Die Nachricht wurde nur gespeichert, nicht versendet. |
blocked | Versand gesperrt, weil die Prüfung nicht bestanden oder die Freigabe nicht erteilt ist. Grund in reason. |
failed | Fehler vor der Übergabe an den Mailserver; es ging nichts hinaus. Grund in reason. |
queued | Freigegeben, wird in Kürze versendet. |
unknown | Ergebnis unklar. Nicht automatisch wiederholen, sondern nachfragen. |
Scheitert das Ausstellen, etwa wegen fehlender Käuferreferenz, antwortet die Schnittstelle mit einem Fehler – und es bleibt weder ein Entwurf noch ein neu angelegter Kunde zurück.
Beispiel in PHP
<?php
$ch = curl_init('https://api.erechnung2027.entgema.com/v1/submit');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
'Idempotency-Key: auftrag-' . $orderId, // je Auftrag gleich, damit nichts doppelt entsteht
],
CURLOPT_POSTFIELDS => json_encode($rechnung, JSON_UNESCAPED_UNICODE),
]);
$antwort = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 201 = angenommen
if ($status === 201) {
echo $antwort['invoice']['number']; // z. B. RE-2026-000012
echo $antwort['dispatch']['status'] ?? ''; // sent | test_mode | blocked | failed
} else {
echo $antwort['error'];
}
Versand anstoßen
POSThttps://api.erechnung2027.entgema.com/v1/invoices/{id}/dispatch
Versendet eine bereits ausgestellte Rechnung. {id} ist die Nummer oder UUID aus der Antwort der Einlieferung. Benötigt email.send.
{
"recipient": "andere.adresse@beispielkunde.de",
"subject": "Ihre Rechnung",
"body": "Guten Tag, …",
"selection": ["zugferd", "xrechnung"],
"resend": false
}
Alle Felder sind freiwillig; ohne Angaben gelten die Vorlage und die Adresse des Kunden. Ging an denselben Empfänger bereits etwas hinaus, wird nicht erneut gesendet und die Antwort enthält "already_sent": true. Mit "resend": true erzwingen Sie einen zweiten Versand.
Stand abfragen
GEThttps://api.erechnung2027.entgema.com/v1/invoices/{id}/summary
Liefert denselben kompakten Aufbau wie die Einlieferung: Nummer, Beträge, Dateien, Prüfung und Zahlungsstand (invoice.payment_status: unpaid, partial, paid).
Dateien abholen
GEThttps://api.erechnung2027.entgema.com/v1/invoices/{id}/files/{format}
{format} | Inhalt |
|---|---|
zugferd | ZUGFeRD-2.5-PDF (PDF/A-3 mit eingebetteter XML) |
xrechnung | XRechnung 3.0.2 als XML (CII) |
zugferd_xml | die im PDF eingebettete XML als eigene Datei |
Die Antwort der Einlieferung nennt zu jeder Datei Größe und SHA-256, damit Sie den Abruf prüfen können.
E-Rechnung prüfen und lesen
POSThttps://api.erechnung2027.entgema.com/v1/inspect
Prüft eine beliebige E-Rechnung – XRechnung oder EN 16931 als UBL oder CII, ZUGFeRD-/Factur-X-PDF – und liefert das Prüfergebnis sowie den Inhalt als JSON. Die Datei wird nicht gespeichert und keiner Rechnung zugeordnet. Berechtigung read, kein Idempotency-Key nötig, höchstens 10 MB.
curl -X POST "https://api.erechnung2027.entgema.com/v1/inspect?filename=rechnung.xml" \ -H "Authorization: Bearer rw_IHR_SCHLUESSEL" \ --data-binary @rechnung.xml
Alternativ als Formular-Upload im Feld file (multipart/form-data). Die Antwort enthält validation (passed, errors, warnings mit Regelkennung wie BR-CO-15), format (Syntax, Profil) und invoice (Verkäufer, Käufer, Positionen, Steuern, Summen, Zahlung). Es ist eine Teilprüfung; die Referenzprüfung mit KoSIT-Validator und veraPDF ersetzt sie nicht. Dieselbe Prüfung steht ohne Schlüssel im Browser unter https://erechnung2027.entgema.com/pruefen bereit.
Weitere Aufrufe
| Aufruf | Zweck |
|---|---|
GET /invoices?q=&status=&customer=&page= | Rechnungen suchen und blättern (25 je Seite) |
GET /invoices/{id} | vollständige Rechnung mit allen Positionen |
GET /invoices/{id}/emails | Korrespondenz zur Rechnung |
POST /invoices/{id}/payments | Zahlung buchen: amount, paid_on, reference |
POST /invoices/{id}/cancel | Stornoentwurf anlegen; danach POST /invoices/{neue-id}/issue |
POST /customers, GET/PUT /customers/{id} | Kunden anlegen, lesen, ändern |
GET /customers/{id}/correspondence | gesamte Korrespondenz mit einem Kunden |
GET /stats?year=JJJJ | Jahresauswertung |
POST /quotes, GET/PUT/DELETE /quotes/{id} | Angebot als Entwurf anlegen, lesen, ändern, löschen: customer_id, issue_date, valid_until, lines, terms, note |
POST /quotes/{id}/finalize | Angebotsnummer vergeben und Stand festhalten; danach GET /quotes/{id}/pdf |
POST /quotes/{id}/send | Angebot per E-Mail senden: recipient, subject, body (Vorgaben über GET /quotes/{id}/mail); Berechtigung email.send |
POST /quotes/{id}/status, POST /quotes/{id}/invoice | Status setzen (accepted, declined, open, draft); Angebot in einen Rechnungsentwurf übernehmen |
GET /reminders | überfällige Rechnungen mit Mahnstand und nächster Stufe |
POST /invoices/{id}/reminders, POST /reminders/{id}/send | nächste Mahnstufe anlegen; Mahnschreiben senden (GET /reminders/{id}/pdf liefert das PDF) |
GET/POST /recurring, PUT/DELETE /recurring/{id} | Serien wiederkehrender Rechnungen: invoice_id (Vorlage), name, interval, next_date, period, due_days, mode, end_date; Berechtigung issue |
POST /recurring/{id}/run, /pause, /resume | Serie sofort ausführen, anhalten, fortsetzen |
Fehler
Fehlerantworten haben immer die Form {"error": "…"}. Der Text nennt die Ursache und, wo möglich, das betroffene Feld.
| Code | Bedeutung | Was tun |
|---|---|---|
400 | Idempotency-Key fehlt oder ungültig, JSON nicht lesbar | Anfrage korrigieren |
401 | Schlüssel fehlt oder ist ungültig | Kopf Authorization prüfen |
403 | Schlüssel hat die Berechtigung nicht | Betreiber um Erweiterung bitten |
404 | Rechnung, Kunde oder Datei nicht gefunden | Nummer prüfen |
409 | Idempotency-Key mit anderem Inhalt wiederverwendet; Dokument bereits ausgestellt | neuen Schlüssel verwenden bzw. Stand abfragen |
422 | Angaben fehlen oder sind ungültig | genanntes Feld korrigieren |
429 | zu viele Aufrufe pro Minute | eine Minute warten |
5xx | Störung auf dem Server | mit demselben Idempotency-Key wiederholen |