📖
KSeF API 2.0

Guide API KSeF 2.0

Référence technique complète pour l'intégration avec l'API KSeF du Ministère des Finances polonais

Tester mes factures

Avertissement

Ce guide est fourni à titre informatif et se base sur la documentation API KSeF 2.0 et nos tests réels sur l'environnement TEST. Les spécifications peuvent évoluer. Consultez toujours la documentation officielle du Ministère des Finances polonais pour les informations les plus récentes.

1. Environnements

Le KSeF propose trois environnements distincts. Utilisez toujours TEST ou DEMO pour le développement.

EnvironnementURLUsage
TESThttps://api-test.ksef.mf.gov.pl/v2Tests libres, NIP fictifs
DEMOhttps://api-demo.ksef.mf.gov.pl/v2Démonstration
PRODhttps://api.ksef.mf.gov.pl/v2Production (obligatoire depuis le 01/02/2026)

2. Authentification

Chaque session API nécessite une authentification par token. Le flux complet utilise un chiffrement RSA-OAEP du token avec la clé publique du KSeF.

Flux complet (token API)

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

Headers requis pour les appels authentifiés

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

Clés publiques

GET /security/public-key-certificates renvoie 2 certificats :

UsageUtilisation
KsefTokenEncryptionChiffrement du token lors de l'authentification
SymmetricKeyEncryptionChiffrement de la clé AES de session

Pas de champ fingerprint dans la réponse (contrairement à la documentation).

3. Session Online (interactive)

Pour envoyer des factures sans pièce jointe, une par une.

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

Ouverture de session

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

Le client génère la clé AES-256 et l'IV, chiffre la clé avec RSA, envoie les deux.

Envoi d'une facture

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

Chiffrement AES-256-CBC avec PKCS#7 padding. Même clé/IV que la session.

4. Session Batch (wsadowa)

Pour envoyer des factures avec ou sans pièces jointes, en lot (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

Ouverture session batch

{
  "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": "..."
  }
}
ChampValeur
batchFile.fileSizeTaille du ZIP avant chiffrement
batchFile.fileHashSHA256 du ZIP avant chiffrement
fileParts[].fileSizeTaille du ZIP après chiffrement
fileParts[].fileHashSHA256 du ZIP après chiffrement

Upload : la réponse contient partUploadRequests avec URL, méthode (PUT) et headers (x-ms-blob-type: BlockBlob). Envoyer les bytes chiffrés bruts, sans Authorization header.

Chaque facture est traitée indépendamment. Une erreur sur une facture ne bloque PAS les autres.

Contrairement à une idée reçue, le traitement batch n'est pas atomique : les factures valides reçoivent leur ksefNumber même si d'autres factures du même lot sont rejetées.

Retours par facture

Après fermeture de la session batch, chaque facture est traitée indépendamment. Consultez les résultats via deux endpoints distincts.

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

Le traitement est parallèle : les factures acceptées et rejetées peuvent apparaître dans un ordre différent de celui du ZIP.

5. Codes de traitement

Les réponses API utilisent des codes de traitement (processingCode) pour indiquer l'état de la requête. Un même code peut avoir des significations légèrement différentes selon l'endpoint (auth, session, facture, export).

Progression (100-299)

CodeSignification
100Processus enregistré / accepté pour traitement
150En cours de traitement (remplace l'ancien code 300 depuis RC3)
170Traitement terminé
200Succès → ksefNumber disponible, session traitée, export terminé
210Export expiré, plus disponible au téléchargement

Erreurs (400-550)

CodeSignification
400Échec opération, demande rejetée
405Erreur vérification paczka (sanity check) / erreur session
410Identifiants incohérents, portée permissions invalide
415Permissions manquantes, erreur déchiffrement clé, PJ non autorisées
420Filtres trop larges, limite factures dépassée, permission refusée
425Token invalidé / hash fichier invalide
429Rate limit dépassé (~100/s, ~300/min, ~1200/h)
430Erreur décompression, erreur vérification facture, rôle manquant
435Erreur déchiffrement fichier (chiffrement incorrect)
440Session annulée (timeout upload), doublon facture, opération interdite
441Erreur vérification sous-processus traitement facture
445Erreur finalisation, aucune facture valide trouvée
450Token invalide, erreur structure facture, XML invalide
460Échec certificat (invalide, chaîne non fiable, révoqué)
470Tentative d'utilisation des méthodes d'autorisation d'une personne décédée
480Auth bloquée : suspicion incident sécurité (contacter MF via formulaire)
500Erreur serveur inconnue
550Opération annulée par le système (atomique, aucun traitement partiel). Réessayer.

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

6. Limites

ParamètreValeur
Taille max facture sans PJ1 MB
Taille max facture avec PJ3 MB (configurable jusqu'à 10 MB)
Factures max par session batch10 000 000
Taille max ZIP5 GB
Parts max par ZIP50 (100 MB chacune)
Timeout session batch non fermée12h → annulation auto (code 440)

Vérifiable via GET /limits/context.

7. Pièces jointes (Zalacznik)

Prérequis

  • 1.Activation : POST /testdata/attachment avec {"nip": "..."} (env TEST). En PROD : déclaration via e-Urząd Skarbowy.
  • 2.Session batch obligatoire : le mode online rejette les PJ (code 415).

Vérification

GET /permissions/attachments/status (authenticated)

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

Structure XML

'<Zalacznik>' est un enfant direct de '<Faktura>' (pas de '<Fa>'), avec structure structurée :

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

Types de colonnes : txt, int, dec, date.

Codes erreur PJ

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

8. Endpoints testdata (env TEST)

Pas besoin d'authentification. Ces endpoints permettent de configurer l'environnement de test.

EndpointMéthodeStatutNotes
/testdata/subjectPOSTOK{"subjectNip": "...", "description": "..."}
/testdata/personPOSTOK{"nip": "...", "pesel": "...", "description": "..."}
/testdata/attachmentPOSTOK{"nip": "..."} — active les pièces jointes
/testdata/attachment/revokePOSTOK{"nip": "..."} — révocation non immédiate
/testdata/permissionsPOST500Cassé depuis le lancement KSeF 2.0

9. Endpoints d'information

Endpoints authentifiés pour consulter l'état de votre compte et de vos factures.

EndpointDescription
/permissions/attachments/statusStatut autorisation pièces jointes
/limits/contextLimites de session (taille max, etc.)
/rate-limitsRate limits actuels
/auth/sessionsSessions actives
/invoices/query/metadataRecherche de factures (filtre hasAttachment)
/invoices/ksef/{ksefNumber}Télécharger une facture par numéro KSeF

10. Problèmes connus

Points d'attention lors de l'intégration avec l'API KSeF, basés sur nos tests réels :

ProblèmeSourceDétails
POST /testdata/permissions renvoie 500#296Cassé depuis le lancement KSeF 2.0. Même avec le format exact du schéma OpenAPI, le serveur renvoie 500 Internal Server Error.
Révocation PJ non immédiateTests 04/02/2026Après appel de /testdata/attachment/revoke, isAttachmentAllowed reste true avec un revokedDate futur.
Serveur TEST lent (code 150 prolongé)#408, #278Post-lancement, le traitement peut rester en code 150 ("En cours de traitement") plus longtemps que prévu.
PJ rejetée en mode online (415)#674Pas un bug : les PJ nécessitent obligatoirement une session batch. Le mode online renvoie 415.

Besoin d'aide pour l'intégration KSeF ?

Nous vous accompagnons dans l'intégration API : authentification, envoi de factures, gestion des erreurs et mise en production.

Avertissement

Ce guide est fourni à titre informatif et se base sur la documentation API KSeF 2.0 et nos tests réels sur l'environnement TEST. Les spécifications peuvent évoluer. Consultez toujours la documentation officielle du Ministère des Finances polonais pour les informations les plus récentes.