📖
KSeF API 2.0

KSeF API 2.0 Leitfaden

Vollständige technische Referenz für die Integration mit der KSeF-API des polnischen Finanzministeriums

Meine Rechnungen testen

Hinweis

Dieser Leitfaden dient Informationszwecken und basiert auf der KSeF API 2.0-Dokumentation und unseren realen Tests in der TEST-Umgebung. Die Spezifikationen können sich ändern. Konsultieren Sie immer die offizielle Dokumentation des polnischen Finanzministeriums für aktuelle Informationen.

1. Umgebungen

KSeF bietet drei verschiedene Umgebungen. Verwenden Sie für die Entwicklung immer TEST oder DEMO.

UmgebungURLZweck
TESThttps://api-test.ksef.mf.gov.pl/v2Freie Tests, fiktive NIPs
DEMOhttps://api-demo.ksef.mf.gov.pl/v2Demonstration
PRODhttps://api.ksef.mf.gov.pl/v2Produktion (verpflichtend seit 01.02.2026)

2. Authentifizierung

Jede API-Sitzung erfordert eine Token-Authentifizierung. Der vollständige Ablauf verwendet RSA-OAEP-Verschlüsselung des Tokens mit dem öffentlichen KSeF-Schlüssel.

Vollständiger Ablauf (API-Token)

1. GET  /security/public-key-certificates     → RSA keys
2. POST /auth/challenge                        → challenge + timestampMs
3. RSA-OAEP(token|timestampMs)                 → encrypt with "KsefTokenEncryption" key
4. POST /auth/ksef-token                       → challenge + encryptedToken
   → authenticationToken + referenceNumber (HTTP 202)
5. GET  /auth/{referenceNumber}                → poll until code=200
6. POST /auth/token/redeem                     → exchange → accessToken

Erforderliche Header für authentifizierte Aufrufe

Authorization: Bearer {accessToken}
Accept: application/json
Content-Type: application/json

Öffentliche Schlüssel

GET /security/public-key-certificates gibt 2 Zertifikate zurück:

UsageVerwendung
KsefTokenEncryptionToken-Verschlüsselung bei der Authentifizierung
SymmetricKeyEncryptionVerschlüsselung des AES-Sitzungsschlüssels

Kein Fingerprint-Feld in der Antwort (entgegen der Dokumentation).

3. Online-Sitzung (interaktiv)

Zum Senden von Rechnungen ohne Anhänge, einzeln.

1. POST /sessions/online                           → open session
2. POST /sessions/online/{ref}/invoices             → send invoice
3. GET  /sessions/{ref}/invoices/{invoiceRef}        → check status
4. POST /sessions/online/{ref}/close                → close session

Sitzung öffnen

{
  "formCode": {"systemCode": "FA (3)", "schemaVersion": "1-0E", "value": "FA"},
  "encryption": {
    "encryptedSymmetricKey": "RSA-OAEP(aes_key, cert_SymmetricKeyEncryption)",
    "initializationVector": "base64(iv_16_bytes)"
  }
}

Der Client generiert den AES-256-Schlüssel und IV, verschlüsselt den Schlüssel mit RSA und sendet beides.

Rechnung senden

{
  "invoiceHash": "base64(SHA256(xml_raw))",
  "invoiceSize": 2048,
  "encryptedInvoiceHash": "base64(SHA256(xml_encrypted))",
  "encryptedInvoiceSize": 2064,
  "encryptedInvoiceContent": "base64(AES-256-CBC(xml_raw))"
}

AES-256-CBC-Verschlüsselung mit PKCS#7-Padding. Gleicher Schlüssel/IV wie die Sitzung.

4. Batch-Sitzung (wsadowa)

Zum Senden von Rechnungen mit oder ohne Anhänge, als Stapel (ZIP).

1. Create ZIP containing XML invoices (faktura_1.xml, faktura_2.xml, ...)
2. Encrypt ZIP with AES-256-CBC + PKCS#7 (NO IV prepend)
3. POST /sessions/batch           → open session, receive upload URL
4. PUT  {uploadUrl}               → upload encrypted ZIP (raw bytes)
5. POST /sessions/batch/{ref}/close  → close and start processing
6. GET  /sessions/{ref}           → poll session status
7. GET  /sessions/{ref}/invoices  → accepted invoices
8. GET  /sessions/{ref}/invoices/failed → rejected invoices

Batch-Sitzung öffnen

{
  "formCode": {"systemCode": "FA (3)", "schemaVersion": "1-0E", "value": "FA"},
  "batchFile": {
    "fileSize": 1078,
    "fileHash": "base64(SHA256(zip_raw))",
    "fileParts": [{
      "ordinalNumber": 1,
      "fileSize": 1088,
      "fileHash": "base64(SHA256(zip_encrypted))"
    }]
  },
  "encryption": {
    "encryptedSymmetricKey": "...",
    "initializationVector": "..."
  }
}
FeldWert
batchFile.fileSizeZIP-Größe vor Verschlüsselung
batchFile.fileHashSHA256 der ZIP vor Verschlüsselung
fileParts[].fileSizeZIP-Größe nach Verschlüsselung
fileParts[].fileHashSHA256 der ZIP nach Verschlüsselung

Upload: Die Antwort enthält partUploadRequests mit URL, Methode (PUT) und Headern (x-ms-blob-type: BlockBlob). Senden Sie rohe verschlüsselte Bytes, ohne Authorization-Header.

Jede Rechnung wird unabhängig verarbeitet. Ein Fehler bei einer Rechnung blockiert NICHT die anderen.

Entgegen einer verbreiteten Annahme ist die Batch-Verarbeitung nicht atomar: Gültige Rechnungen erhalten ihre ksefNumber, auch wenn andere Rechnungen im selben Batch abgelehnt werden.

Ergebnisse pro Rechnung

Nach dem Schließen der Batch-Sitzung wird jede Rechnung unabhängig verarbeitet. Ergebnisse über zwei separate Endpoints abrufen.

GET /sessions/{ref}/invoices          → accepted invoices (with ksefNumber)
GET /sessions/{ref}/invoices/failed   → rejected invoices (with processingCode + error)

Die Verarbeitung ist parallel: Akzeptierte und abgelehnte Rechnungen können in anderer Reihenfolge als im ZIP erscheinen.

5. Verarbeitungscodes

API-Antworten verwenden Verarbeitungscodes (processingCode) zur Angabe des Anfragestatus. Derselbe Code kann je nach Endpoint (Auth, Sitzung, Rechnung, Export) leicht unterschiedliche Bedeutungen haben.

Fortschritt (100-299)

CodeBedeutung
100Prozess registriert / zur Verarbeitung angenommen
150Verarbeitung läuft (ersetzt den alten Code 300 seit RC3)
170Verarbeitung abgeschlossen
200Erfolg → ksefNumber verfügbar, Sitzung verarbeitet, Export abgeschlossen
210Export abgelaufen, nicht mehr zum Download verfügbar

Fehler (400-550)

CodeBedeutung
400Operation fehlgeschlagen, Anfrage abgelehnt
405Paketverifizierungsfehler (Sanity Check) / Sitzungsfehler
410Inkonsistente Identifikatoren, ungültiger Berechtigungsumfang
415Fehlende Berechtigungen, Schlüssel-Entschlüsselungsfehler, Anhänge nicht erlaubt
420Filter zu breit, Rechnungslimit überschritten, Berechtigung verweigert
425Token ungültig / ungültiger Datei-Hash
429Rate-Limit überschritten (~100/s, ~300/min, ~1200/h)
430Dekomprimierungsfehler, Rechnungsverifizierungsfehler, fehlende Rolle
435Dateientschlüsselungsfehler (fehlerhafte Verschlüsselung)
440Sitzung abgebrochen (Upload-Timeout), doppelte Rechnung, verbotene Operation
441Fehler bei der Verifizierung des Rechnungsverarbeitungs-Unterprozesses
445Finalisierungsfehler, keine gültige Rechnung gefunden
450Ungültiger Token, Rechnungsstrukturfehler, ungültiges XML
460Zertifikatsfehler (ungültig, nicht vertrauenswürdige Kette, widerrufen)
470Versuch, Autorisierungsmethoden einer verstorbenen Person zu verwenden
480Auth blockiert: Verdacht auf Sicherheitsvorfall (MF über Formular kontaktieren)
500Unbekannter Serverfehler
550Operation vom System abgebrochen (atomar, keine Teilverarbeitung). Erneut versuchen.

Source : Issue #526, OpenAPI spec, api-changelog.md

6. Limits

ParameterWert
Max. Rechnungsgröße ohne Anhänge1 MB
Max. Rechnungsgröße mit Anhängen3 MB (konfigurierbar bis 10 MB)
Max. Rechnungen pro Batch-Sitzung10 000 000
Max. ZIP-Größe5 GB
Max. Teile pro ZIP50 (je 100 MB)
Timeout nicht geschlossener Batch-Sitzung12h → automatische Stornierung (Code 440)

Überprüfbar über GET /limits/context.

7. Anhänge (Zalacznik)

Voraussetzungen

  • 1.Aktivierung : POST /testdata/attachment mit {"nip": "..."} (TEST-Umgebung). In PROD: Erklärung über e-Urząd Skarbowy.
  • 2.Batch-Sitzung erforderlich : der Online-Modus lehnt Anhänge ab (Code 415).

Überprüfung

GET /permissions/attachments/status (authenticated)

{"isAttachmentAllowed": true}
// or with revocation date:
{"isAttachmentAllowed": true, "revokedDate": "2026-12-31T23:59:59+00:00"}

XML-Struktur

'<Zalacznik>' ist ein direktes Kind von '<Faktura>' (nicht '<Fa>'), mit strukturiertem Inhalt:

<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/">
  <Naglowek>...</Naglowek>
  <Podmiot1>...</Podmiot1>
  <Podmiot2>...</Podmiot2>
  <Fa>...</Fa>
  <Zalacznik>
    <BlokDanych>
      <MetaDane>
        <ZKlucz>Key</ZKlucz>
        <ZWartosc>Value</ZWartosc>
      </MetaDane>
      <Tabela>
        <Opis>Table description</Opis>
        <TNaglowek>
          <Kol Typ="txt"><NKom>Column 1</NKom></Kol>
          <Kol Typ="int"><NKom>Column 2</NKom></Kol>
        </TNaglowek>
        <Wiersz>
          <WKom>Value 1</WKom>
          <WKom>42</WKom>
        </Wiersz>
      </Tabela>
    </BlokDanych>
  </Zalacznik>
</Faktura>

Spaltentypen: txt, int, dec, date.

Anhang-Fehlercodes

CodeModeMessage
415Online"Wysylanie faktury z zalacznikiem w trybie interaktywnym nie jest dozwolone"
410Batch"Sprzedawca {NIP} nie posiada zgody do wysylania faktur z zalacznikami"

8. Testdata-Endpoints (TEST-Umgebung)

Keine Authentifizierung erforderlich. Diese Endpoints ermöglichen die Konfiguration der Testumgebung.

EndpointMethodeStatusNotes
/testdata/subjectPOSTOK{"subjectNip": "...", "description": "..."}
/testdata/personPOSTOK{"nip": "...", "pesel": "...", "description": "..."}
/testdata/attachmentPOSTOK{"nip": "..."} — aktiviert Anhänge
/testdata/attachment/revokePOSTOK{"nip": "..."} — Widerruf nicht sofort wirksam
/testdata/permissionsPOST500Defekt seit KSeF 2.0 Start

9. Informations-Endpoints

Authentifizierte Endpoints zur Überprüfung des Konto- und Rechnungsstatus.

EndpointDescription
/permissions/attachments/statusAutorisierungsstatus für Anhänge
/limits/contextSitzungslimits (max. Größe usw.)
/rate-limitsAktuelle Rate-Limits
/auth/sessionsAktive Sitzungen
/invoices/query/metadataRechnungssuche (hasAttachment-Filter)
/invoices/ksef/{ksefNumber}Rechnung nach KSeF-Nummer herunterladen

10. Bekannte Probleme

Wichtige Punkte bei der Integration mit der KSeF-API, basierend auf unseren realen Tests:

ProblemSourceDetails
POST /testdata/permissions gibt 500 zurück#296Defekt seit KSeF 2.0 Start. Selbst mit dem exakten OpenAPI-Schema-Format gibt der Server 500 Internal Server Error zurück.
Anhang-Widerruf nicht sofort wirksamTests 04.02.2026Nach Aufruf von /testdata/attachment/revoke bleibt isAttachmentAllowed auf true mit einem zukünftigen revokedDate.
TEST-Server langsam (verlängerter Code 150)#408, #278Nach dem Start kann die Verarbeitung länger als erwartet im Code 150 ("Verarbeitung läuft") verbleiben.
Anhang im Online-Modus abgelehnt (415)#674Kein Bug: Anhänge erfordern eine Batch-Sitzung. Der Online-Modus gibt 415 zurück.

Brauchen Sie Hilfe bei der KSeF-Integration?

Wir unterstützen Sie bei der API-Integration: Authentifizierung, Rechnungsversand, Fehlerbehandlung und Produktiveinführung.

Hinweis

Dieser Leitfaden dient Informationszwecken und basiert auf der KSeF API 2.0-Dokumentation und unseren realen Tests in der TEST-Umgebung. Die Spezifikationen können sich ändern. Konsultieren Sie immer die offizielle Dokumentation des polnischen Finanzministeriums für aktuelle Informationen.