Quickstart
Sechzig Sekunden vom Konto bis zum ersten API-Call — drei Befehle, außer curl nichts zu installieren.
Key holen
≈ 30 sKonto erstellen (E-Mail + Passwort, für das Freikontingent ohne Zahlungsdaten), dann im Dashboard Key erstellen drücken. Das Secret wird genau einmal angezeigt — direkt in die Shell kopieren:
export KEY=sk_test_… # der eben erstellte Key
Abrechnung: Freikontingent jeden Monat, danach Prepaid-Guthaben – kein Abo.
Der erste Call
≈ 20 sEine vorhandene XRechnung oder ZUGFeRD-Datei prüfen — oder eine aus JSON erzeugen. Abrechnung: Prüfen = 1 Dokument; Erzeugen = 3 Dokumente (Erzeugung inklusive Gegenprüfung):
curl -X POST https://formkorrekt.com/v1/invoices/validate \
-H "Authorization: Bearer $KEY" \
--data-binary @rechnung.xml
curl -X POST https://formkorrekt.com/v1/invoices/generate \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-o rechnung.xml \
-d '{"target": "xrechnung-ubl", "invoice": {
"number": "RE-2026-0042", "issue_date": "2026-09-25",
"delivery_date": "2026-09-24", "currency": "EUR",
"seller": {"name": "Muster GmbH", "vat_id": "DE123456789",
"email": "rechnung@muster.example",
"contact": {"name": "Erika Muster", "phone": "+49 30 1234567",
"email": "erika.muster@muster.example"},
"address": {"street": "Musterstr. 1", "zip": "10115",
"city": "Berlin", "country": "DE"}},
"buyer": {"name": "Kunde AG", "buyer_reference": "K-1001",
"email": "einkauf@kunde.example",
"address": {"street": "Kundenweg 2", "zip": "80331",
"city": "München", "country": "DE"}},
"lines": [{"name": "Beratung", "quantity": 10, "unit": "HUR",
"unit_price": 120.00, "vat_rate": 19.0}],
"payment": {"iban": "DE02120300000000202051", "terms_days": 14}}}'
target: xrechnung-ubl, xrechnung-cii
oder zugferd-en16931 (PDF/A-3). Jede erzeugte Datei wird vor
der Auslieferung gegen XRechnung 3.0.2 re-validiert
(X-Validation-Status: valid). Pflicht sind
seller.contact (name, phone,
email) und buyer.email — Daten setzen wir nie
selbst ein. Ebenfalls Pflicht: address.country bei Verkäufer und
Käufer sowie quantity, unit_price und
vat_rate in jeder Position. Optional: delivery_date
(ISO-Datum; ohne Angabe entfällt es), payment.terms_days
(setzt das Fälligkeitsdatum; ohne Angabe gibt es keins) und
payment.terms_text (eigene Zahlungsbedingungen). Vorgaben:
Währung EUR, Einheit C62. Fehlt ein Pflichtfeld, kommt 422 VALIDATION mit dem
Feldnamen, z. B.
seller.contact.phone is required for XRechnung (BR-DE-6). seller.email (elektronische Adresse) ist
optional; ohne sie gilt die Kontakt-E-Mail.
Reparieren statt nur prüfen. Nur deterministische
Korrekturen: Summen werden neu berechnet, die
XRechnung-Spezifikations-ID gesetzt, Datums- und Zahlenformate
normalisiert. Nichts wird geraten — alles, was Ihre Angabe braucht,
bleibt in findings stehen.
curl -X POST https://formkorrekt.com/v1/invoices/repair \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/xml" \
--data-binary @rechnung.xml
{
"status": "valid",
"repaired": true,
"document": "<?xml version=\"1.0\" ...",
"applied": [
{"code": "BR-CO-16", "path": "/Invoice/cac:LegalMonetaryTotal/cbc:PayableAmount",
"action": "recalculated", "before": "1.00", "after": "297.50"}
],
"findings": []
}
applied listet jede
Änderung (Regel-Code, XPath, vorher/nachher). repaired: false
heißt: Dokument unverändert zurück. Abrechnung: eine Reparatur = 3 Dokumente
(1, wenn nichts zu reparieren war). Nur XML (UBL/CII); PDF liefert 422
REPAIR_FORMAT.
Wenn etwas schiefgeht
≈ 10 s| 401 | Key fehlt, ist falsch oder widerrufen. |
| 402 | Freikontingent verbraucht, Guthaben reicht nicht — im Dashboard aufladen. |
| 422 | Unbrauchbare Anfrage: leerer Body, fehlendes Feld (z. B. seller.contact bei /generate), erzeugte Datei nicht bestanden, PDF an /repair — siehe Tabelle unten. |
| 429 | Rate-Limit — Retry-After Sekunden warten. |
Eine ungültige Rechnung
ist ein Ergebnis, kein Fehler: für jede nicht leere Datei antwortet
/v1/invoices/validate mit 200 und
"status": "invalid" samt findings (Regel-Code,
deutsche Meldung, fix_hint); /repair ebenso nach
der Reparatur. 422 heißt, die Anfrage selbst war unbrauchbar:
VALIDATION (leerer Body oder Multipart ohne file bei
/validate und /repair; fehlendes oder ungültiges
Feld bei /generate), INVOICE_INVALID
(/generate: erzeugte Datei hat die Prüfung nicht bestanden),
REPAIR_FORMAT (/repair: kein UBL/CII-XML) und
IDEMPOTENCY_CONFLICT (jeder POST).
Alle Fehlercodes
(Feld error_code)
| 401 | UNAUTHORIZED | API-Key fehlt, hat ein falsches Format oder ist widerrufen. |
| 402 | CREDIT_EXHAUSTED | Freikontingent verbraucht und zu wenig Guthaben; im Dashboard aufladen (top_up_url). |
| 413 | PAYLOAD_TOO_LARGE | Datei größer als 10 MB. |
| 422 | VALIDATION | Ungültige Eingabe: leerer Body, Multipart ohne 'file' oder ein fehlendes /generate-Feld (z. B. seller.contact.phone); detail nennt es. |
| 422 | INVOICE_INVALID | /generate: die erzeugte Datei hat die XRechnung-Prüfung nicht bestanden; der Body listet jede Regel mit fix_hint. Nicht berechnet. |
| 422 | REPAIR_FORMAT | /repair: Eingabe ist kein UBL/CII-XML (z. B. ein PDF). |
| 422 | IDEMPOTENCY_CONFLICT | Idempotency-Key wurde schon mit einem anderen Inhalt verwendet. |
| 409 | IDEMPOTENCY_IN_PROGRESS | Eine Anfrage mit demselben Idempotency-Key läuft noch; nach Retry-After Sekunden erneut versuchen. |
| 409 | IDEMPOTENCY_KEY_EXHAUSTED | Der Idempotency-Key wurde schon 3-mal wiederholt oder die erste Anfrage ist älter als eine Stunde; einen neuen Key senden (wird neu berechnet). |
| 429 | RATE_LIMITED | Rate-Limit; Retry-After Sekunden warten. |
| 500 | INTERNAL | Interner Fehler; bitte request_id angeben. |
| 502 | UPSTREAM_UNAVAILABLE | Das Verarbeitungsmodul ist nicht erreichbar oder scheiterte; später erneut versuchen. |
| 503 | SERVICE_BUSY | Ausgelastet; nach Retry-After Sekunden erneut versuchen. |
| 504 | UPSTREAM_TIMEOUT | Das Verarbeitungsmodul hat nicht rechtzeitig geantwortet. |
Fehler sind RFC 7807
application/problem+json. Jede Antwort trägt eine
X-Request-Id — bei Rückfragen bitte angeben. POSTs sicher
wiederholen: Header Idempotency-Key (24 h gültig) – eine
Wiederholung mit demselben Key und Inhalt wird einmal berechnet (bis zu 3
Wiederholungen innerhalb einer Stunde); Audio und
Rechnungsergebnisse werden neu erzeugt, nie zwischengespeichert. Alles
Weitere: API-Referenz.
Für KI-Agenten (MCP)
≈ 30 sDieselbe API als Werkzeuge für Claude, Cursor oder VS Code – derselbe Key, dieselben Preise. In Claude Code:
claude mcp add --transport http formkorrekt https://formkorrekt.com/mcp --header "Authorization: Bearer $KEY"
Cursor, VS Code, Claude Desktop und die Liste der Tools: MCP einrichten.
Gesendete Inhalte werden nur im Arbeitsspeicher verarbeitet und nie gespeichert — nur Zeitpunkt, Menge und SHA-256 für die Abrechnung.