formkorrekt
Menü

Quickstart

Sechzig Sekunden vom Konto bis zum ersten API-Call — drei Befehle, außer curl nichts zu installieren.

§ 1

Key holen

≈ 30 s

Konto 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.

§ 2

Der erste Call

≈ 20 s

Eine 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.

§ 3

Wenn etwas schiefgeht

≈ 10 s
401Key fehlt, ist falsch oder widerrufen.
402Freikontingent verbraucht, Guthaben reicht nicht — im Dashboard aufladen.
422Unbrauchbare Anfrage: leerer Body, fehlendes Feld (z. B. seller.contact bei /generate), erzeugte Datei nicht bestanden, PDF an /repair — siehe Tabelle unten.
429Rate-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)

401UNAUTHORIZEDAPI-Key fehlt, hat ein falsches Format oder ist widerrufen.
402CREDIT_EXHAUSTEDFreikontingent verbraucht und zu wenig Guthaben; im Dashboard aufladen (top_up_url).
413PAYLOAD_TOO_LARGEDatei größer als 10 MB.
422VALIDATIONUngültige Eingabe: leerer Body, Multipart ohne 'file' oder ein fehlendes /generate-Feld (z. B. seller.contact.phone); detail nennt es.
422INVOICE_INVALID/generate: die erzeugte Datei hat die XRechnung-Prüfung nicht bestanden; der Body listet jede Regel mit fix_hint. Nicht berechnet.
422REPAIR_FORMAT/repair: Eingabe ist kein UBL/CII-XML (z. B. ein PDF).
422IDEMPOTENCY_CONFLICTIdempotency-Key wurde schon mit einem anderen Inhalt verwendet.
409IDEMPOTENCY_IN_PROGRESSEine Anfrage mit demselben Idempotency-Key läuft noch; nach Retry-After Sekunden erneut versuchen.
409IDEMPOTENCY_KEY_EXHAUSTEDDer Idempotency-Key wurde schon 3-mal wiederholt oder die erste Anfrage ist älter als eine Stunde; einen neuen Key senden (wird neu berechnet).
429RATE_LIMITEDRate-Limit; Retry-After Sekunden warten.
500INTERNALInterner Fehler; bitte request_id angeben.
502UPSTREAM_UNAVAILABLEDas Verarbeitungsmodul ist nicht erreichbar oder scheiterte; später erneut versuchen.
503SERVICE_BUSYAusgelastet; nach Retry-After Sekunden erneut versuchen.
504UPSTREAM_TIMEOUTDas 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.

§ 4

Für KI-Agenten (MCP)

≈ 30 s

Dieselbe 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.