| .. | ||
| Feld-Mapping Cargo Soft zu KSeF (DE).pdf | ||
| information-sheet-on-the-fa-3-logical-structure.pdf | ||
| openapi.json | ||
| README.md | ||
| schemat-FA(3)-v1-0E.xsd | ||
| TEST.md | ||
| test.xml | ||
KSeF API Integration
Java integration for the Polish Krajowy System e-Faktur (KSeF) - the national e-invoicing system for Poland.
Overview
This integration provides secure communication with the KSeF API to upload electronic invoices. It handles the complex multi-step authentication flow and encryption requirements mandated by the Polish tax authorities.
Test environment endpoint:
https://api-test.ksef.mf.gov.pl/api/v2
Production endpoint:
https://api.ksef.mf.gov.pl/api/v2
Components
1. KSeFAuthManager
Manages authentication and session lifecycle for the KSeF API.
Key Responsibilities:
- Multi-step authentication flow
- RSA certificate management
- Session key generation and encryption
- Access token lifecycle management
- Session reuse and validation
2. KSeFAPIService
Provides business-level methods for invoice operations.
Key Responsibilities:
- Invoice encryption (AES-256-CBC)
- Invoice upload to KSeF
- Hash calculation and validation
- Error handling and reporting
Authentication Flow
The KSeF API requires a sophisticated multi-step authentication process:
1. Load Public Keys
└─> GET /security/public-key-certificates
2. Challenge Request
└─> POST /auth/challenge
└─> Returns: challenge + timestamp
3. Token Authentication
└─> POST /auth/ksef-token
└─> Encrypts: token|timestamp with RSA-OAEP SHA-256
└─> Returns: authToken + referenceNumber
4. Token Redemption
└─> POST /auth/token/redeem
└─> Returns: accessToken
5. Open Interactive Session
└─> POST /sessions/online
└─> Generates AES-256 key + IV
└─> Encrypts session key with RSA
└─> Returns: sessionRefNumber + validUntil
Invoice Upload Flow
Once authenticated, invoices can be uploaded:
1. Reuse or Create Session
└─> Validates existing session or creates new one
2. Encrypt Invoice
└─> AES-256-CBC encryption using session key
3. Calculate Hashes
└─> SHA-256 of original XML
└─> SHA-256 of encrypted XML
4. Upload Invoice
└─> POST /sessions/online/{sessionRef}/invoices
└─> Returns: referenceNumber
Security Features
Multi-Layer Encryption
- RSA-OAEP SHA-256: Token encryption with timestamp binding
- RSA-OAEP SHA-1: Session key encryption
- AES-256-CBC: Invoice content encryption
Security Mechanisms
- Replay Attack Protection: Timestamp-bound tokens
- Session Management: Automatic session reuse and validation
- Certificate Validation: Dynamic X.509 certificate loading
- UTC Timezone Handling: Prevents timezone-related vulnerabilities
Usage Example
// Initialize Auth Manager
KSeFAuthManager authManager = new KSeFAuthManager();
authManager.setKsefToken("your-ksef-token");
authManager.setKsefNip("1234567890");
authManager.setKsefEndpoint("https://ksef-test.mf.gov.pl/api/v2");
authManager.init();
// Initialize API Service
KSeFAPIService apiService = new KSeFAPIService();
apiService.kseFAuthManager = authManager;
// Upload Invoice
ItemCollection workitem = new ItemCollection();
FileData fileData = new FileData("invoice.xml", xmlBytes, null, null);
workitem.addFileData(fileData);
String referenceNumber = apiService.uploadInvoice(workitem, "invoice.xml");
System.out.println("Invoice uploaded: " + referenceNumber);
Configuration
Required environment variables:
ksef.api.token=your-ksef-authentication-token
ksef.api.nip=your-company-nip-number
ksef.api.endpoint=https://ksef-test.mf.gov.pl/api/v2
ksef.api.debug=false
Session Management
The KSeFAuthManager automatically handles session lifecycle:
- Session Reuse: Validates
sessionValidUntiltimestamp (UTC) - Auto-Renewal: Opens new session if current one expired
- Thread-Safe: Uses
@Lock(LockType.WRITE)for concurrent access
Testing
Test environment endpoint:
https://ksef-test.mf.gov.pl/api/v2
Production endpoint:
https://ksef.mf.gov.pl/api/v2
See KSeFAPIServiceTest.java for complete test examples.
Error Handling
The implementation uses PluginException for error handling with two error types:
CONFIG_ERROR: Configuration or setup issuesAPI_ERROR: API communication or response errors
Dependencies
- Jakarta EE (EJB, JSON-B)
- Java 11+ (HttpClient, Crypto APIs)
- Imixs Workflow (for document management)
Validate XML
To validate XML results use xmllint. To install run:
$ sudo apt install libxml2-utils
With the bash script src/test/resources/ksef/validate_xml.sh you can test a xml file:
$ ./validate_xml.sh example-invoice-01.xml
or to manual test a xml run:
$ xmllint --noout --schema 'schemat-FA(3)-v1-0E.xsd' example-invoice-01.xml
example-invoice-01.xml validates
KSeF FA(3) Invoice Types: VAT vs. KOR
This section explains the key differences between regular invoices (VAT) and correction invoices (KOR) in the Polish KSeF system using FA(3) structure.
Invoice Types
VAT - Regular Invoice
Standard invoice documenting a sale or service delivery.
KOR - Correction Invoice
Invoice that corrects a previously issued invoice (VAT, ZAL, or ROZ).
Key Differences
| Element | VAT Invoice | KOR Invoice |
|---|---|---|
| RodzajFaktury | VAT |
KOR |
| P_2 (Invoice Number) | 216525 |
216525-KOR (with suffix) |
| P_1 (Invoice Date) | Original date (2024-04-03) | Correction date (2024-04-15) |
| Amount Fields | Absolute values | Difference values (negative or positive) |
| DaneFaKorygowanej | ❌ Not present | ✅ Required - references original invoice |
| FaWiersz (Line Items) | Original values | New/corrected values |
Critical: Amount Fields in KOR
KOR invoices show DIFFERENCES, not absolute amounts!
Example: Correction from 4128.00 → 3500.00 EUR
<!-- VAT Invoice -->
<P_13_1>4128.00</P_13_1> <!-- Total Net -->
<P_14_1>0.00</P_14_1> <!-- Total VAT -->
<P_15>4128.00</P_15> <!-- Total Gross -->
<!-- KOR Invoice -->
<P_13_6_1>-628.00</P_13_6_1> <!-- Difference: 3500 - 4128 = -628 -->
<P_15>-628.00</P_15> <!-- Difference in Total -->
DaneFaKorygowanej Element
Required in KOR invoices - Must appear AFTER <RodzajFaktury>KOR</RodzajFaktury>
<DaneFaKorygowanej>
<DataWystFaKorygowanej>2024-04-03</DataWystFaKorygowanej>
<NrFaKorygowanej>216525</NrFaKorygowanej>
<NrKSeF>1</NrKSeF>
<NrKSeFFaKorygowanej>9552521552-20240403-ABCDEF-123456-AB</NrKSeFFaKorygowanej>
</DaneFaKorygowanej>
| Field | Description |
|---|---|
DataWystFaKorygowanej |
Date of original invoice |
NrFaKorygowanej |
Number of original invoice |
NrKSeF |
Flag: 1 = original was in KSeF |
NrKSeFFaKorygowanej |
KSeF number of original invoice (mandatory if NrKSeF=1) |
⚠️ Critical: The KSeF number must be saved when uploading the original VAT invoice!
FaWiersz in KOR
Line items show the NEW/CORRECTED values, not differences:
<!-- VAT Invoice -->
<FaWiersz>
<P_9A>4128.00</P_9A> <!-- Unit price -->
<P_11>4128.00</P_11> <!-- Net value -->
</FaWiersz>
<!-- KOR Invoice -->
<FaWiersz>
<P_9A>3500.00</P_9A> <!-- NEW unit price -->
<P_11>3500.00</P_11> <!-- NEW net value -->
<P_12>0 KR</P_12> <!-- Tax rate (0% for exempted) -->
</FaWiersz>
Testdaten
Um Testdaten in die lokale Dev Umgebung zu importieren:
-
aus dem Produktiv Archiv System das XML eines Rechnungs-Snapshots unter /docker/transfer speichern
-
per api Call importieren: