Guía API KSeF 2.0
Referencia técnica completa para la integración con la API KSeF del Ministerio de Finanzas polaco
Aviso
Esta guía se proporciona con fines informativos y se basa en la documentación API KSeF 2.0 y nuestras pruebas reales en el entorno TEST. Las especificaciones pueden cambiar. Consulte siempre la documentación oficial del Ministerio de Finanzas polaco para la información más reciente.
1. Entornos
KSeF proporciona tres entornos distintos. Utilice siempre TEST o DEMO para el desarrollo.
| Entorno | URL | Propósito |
|---|---|---|
| TEST | https://api-test.ksef.mf.gov.pl/v2 | Pruebas libres, NIPs ficticios |
| DEMO | https://api-demo.ksef.mf.gov.pl/v2 | Demostración |
| PROD | https://api.ksef.mf.gov.pl/v2 | Producción (obligatorio desde el 01/02/2026) |
2. Autenticación
Cada sesión API requiere autenticación por token. El flujo completo utiliza cifrado RSA-OAEP del token con la clave pública del KSeF.
Flujo completo (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 → accessTokenHeaders requeridos para llamadas autenticadas
Authorization: Bearer {accessToken}
Accept: application/json
Content-Type: application/jsonClaves públicas
GET /security/public-key-certificates devuelve 2 certificados:
| Usage | Uso |
|---|---|
KsefTokenEncryption | Cifrado del token durante la autenticación |
SymmetricKeyEncryption | Cifrado de la clave AES de sesión |
No hay campo fingerprint en la respuesta (contrario a la documentación).
3. Sesión Online (interactiva)
Para enviar facturas sin adjuntos, una a una.
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 sessionApertura de sesión
{
"formCode": {"systemCode": "FA (3)", "schemaVersion": "1-0E", "value": "FA"},
"encryption": {
"encryptedSymmetricKey": "RSA-OAEP(aes_key, cert_SymmetricKeyEncryption)",
"initializationVector": "base64(iv_16_bytes)"
}
}El cliente genera la clave AES-256 y el IV, cifra la clave con RSA y envía ambos.
Envío de una factura
{
"invoiceHash": "base64(SHA256(xml_raw))",
"invoiceSize": 2048,
"encryptedInvoiceHash": "base64(SHA256(xml_encrypted))",
"encryptedInvoiceSize": 2064,
"encryptedInvoiceContent": "base64(AES-256-CBC(xml_raw))"
}Cifrado AES-256-CBC con padding PKCS#7. Misma clave/IV que la sesión.
4. Sesión Batch (wsadowa)
Para enviar facturas con o sin adjuntos, en lote (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 invoicesApertura de sesión 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": "..."
}
}| Campo | Valor |
|---|---|
batchFile.fileSize | Tamaño del ZIP antes del cifrado |
batchFile.fileHash | SHA256 del ZIP antes del cifrado |
fileParts[].fileSize | Tamaño del ZIP después del cifrado |
fileParts[].fileHash | SHA256 del ZIP después del cifrado |
Upload: la respuesta contiene partUploadRequests con URL, método (PUT) y headers (x-ms-blob-type: BlockBlob). Enviar bytes cifrados brutos, sin header Authorization.
Cada factura se procesa de forma independiente. Un error en una factura NO bloquea las demás.
Contrariamente a una idea errónea común, el procesamiento batch no es atómico: las facturas válidas reciben su ksefNumber incluso si otras facturas del mismo lote son rechazadas.
Resultados por factura
Tras cerrar la sesión batch, cada factura se procesa de forma independiente. Consulte los resultados a través de dos endpoints separados.
GET /sessions/{ref}/invoices → accepted invoices (with ksefNumber)
GET /sessions/{ref}/invoices/failed → rejected invoices (with processingCode + error)El procesamiento es paralelo: las facturas aceptadas y rechazadas pueden aparecer en un orden diferente al del ZIP.
5. Códigos de procesamiento
Las respuestas API utilizan códigos de procesamiento (processingCode) para indicar el estado de la solicitud. El mismo código puede tener significados ligeramente diferentes según el endpoint (auth, sesión, factura, exportación).
Progresión (100-299)
| Code | Significado |
|---|---|
| 100 | Proceso registrado / aceptado para procesamiento |
| 150 | Procesamiento en curso (reemplaza el antiguo código 300 desde RC3) |
| 170 | Procesamiento completado |
| 200 | Éxito → ksefNumber disponible, sesión procesada, exportación completada |
| 210 | Exportación expirada, ya no disponible para descarga |
Errores (400-550)
| Code | Significado |
|---|---|
| 400 | Operación fallida, solicitud rechazada |
| 405 | Error de verificación de paquete (sanity check) / error de sesión |
| 410 | Identificadores inconsistentes, alcance de permisos inválido |
| 415 | Permisos faltantes, error de descifrado de clave, adjuntos no permitidos |
| 420 | Filtros demasiado amplios, límite de facturas excedido, permiso denegado |
| 425 | Token invalidado / hash de archivo inválido |
| 429 | Rate limit excedido (~100/s, ~300/min, ~1200/h) |
| 430 | Error de descompresión, error de verificación de factura, rol faltante |
| 435 | Error de descifrado de archivo (cifrado incorrecto) |
| 440 | Sesión cancelada (timeout de upload), factura duplicada, operación prohibida |
| 441 | Error de verificación del subproceso de procesamiento de factura |
| 445 | Error de finalización, ninguna factura válida encontrada |
| 450 | Token inválido, error de estructura de factura, XML inválido |
| 460 | Fallo de certificado (inválido, cadena no confiable, revocado) |
| 470 | Intento de uso de métodos de autorización de una persona fallecida |
| 480 | Auth bloqueada: sospecha de incidente de seguridad (contactar MF vía formulario) |
| 500 | Error de servidor desconocido |
| 550 | Operación cancelada por el sistema (atómica, sin procesamiento parcial). Reintentar. |
Source : Issue #526, OpenAPI spec, api-changelog.md
6. Límites
| Parámetro | Valor |
|---|---|
| Tamaño máx. factura sin adjuntos | 1 MB |
| Tamaño máx. factura con adjuntos | 3 MB (configurable hasta 10 MB) |
| Máx. facturas por sesión batch | 10 000 000 |
| Tamaño máx. ZIP | 5 GB |
| Máx. partes por ZIP | 50 (100 MB cada una) |
| Timeout de sesión batch no cerrada | 12h → cancelación automática (código 440) |
Verificable vía GET /limits/context.
7. Adjuntos (Zalacznik)
Prerrequisitos
- 1.Activación :
POST /testdata/attachmentcon {"nip": "..."} (entorno TEST). En PROD: declaración vía e-Urząd Skarbowy. - 2.Sesión batch obligatoria : el modo online rechaza los adjuntos (código 415).
Verificación
GET /permissions/attachments/status (authenticated)
{"isAttachmentAllowed": true}
// or with revocation date:
{"isAttachmentAllowed": true, "revokedDate": "2026-12-31T23:59:59+00:00"}Estructura XML
'<Zalacznik>' es hijo directo de '<Faktura>' (no de '<Fa>'), con contenido estructurado:
<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>Tipos de columna: txt, int, dec, date.
Códigos de error de adjuntos
| Code | Mode | Message |
|---|---|---|
| 415 | Online | "Wysylanie faktury z zalacznikiem w trybie interaktywnym nie jest dozwolone" |
| 410 | Batch | "Sprzedawca {NIP} nie posiada zgody do wysylania faktur z zalacznikami" |
8. Endpoints testdata (entorno TEST)
No requiere autenticación. Estos endpoints permiten configurar el entorno de prueba.
| Endpoint | Método | Estado | Notes |
|---|---|---|---|
/testdata/subject | POST | OK | {"subjectNip": "...", "description": "..."} |
/testdata/person | POST | OK | {"nip": "...", "pesel": "...", "description": "..."} |
/testdata/attachment | POST | OK | {"nip": "..."} — activa los adjuntos |
/testdata/attachment/revoke | POST | OK | {"nip": "..."} — revocación no inmediata |
/testdata/permissions | POST | 500 | Roto desde el lanzamiento de KSeF 2.0 |
9. Endpoints de información
Endpoints autenticados para consultar el estado de su cuenta y facturas.
| Endpoint | Description |
|---|---|
/permissions/attachments/status | Estado de autorización de adjuntos |
/limits/context | Límites de sesión (tamaño máx., etc.) |
/rate-limits | Rate limits actuales |
/auth/sessions | Sesiones activas |
/invoices/query/metadata | Búsqueda de facturas (filtro hasAttachment) |
/invoices/ksef/{ksefNumber} | Descargar factura por número KSeF |
10. Problemas conocidos
Puntos de atención al integrar con la API KSeF, basados en nuestras pruebas reales:
| Problema | Source | Detalles |
|---|---|---|
| POST /testdata/permissions devuelve 500 | #296 | Roto desde el lanzamiento de KSeF 2.0. Incluso con el formato exacto del esquema OpenAPI, el servidor devuelve 500 Internal Server Error. |
| Revocación de adjuntos no inmediata | Pruebas 04/02/2026 | Tras llamar a /testdata/attachment/revoke, isAttachmentAllowed permanece en true con un revokedDate futuro. |
| Servidor TEST lento (código 150 prolongado) | #408, #278 | Tras el lanzamiento, el procesamiento puede permanecer en código 150 ("Procesamiento en curso") más tiempo de lo esperado. |
| Adjunto rechazado en modo online (415) | #674 | No es un bug: los adjuntos requieren una sesión batch. El modo online devuelve 415. |
Enlaces útiles
¿Necesita ayuda con la integración KSeF?
Le acompañamos en la integración API: autenticación, envío de facturas, gestión de errores y puesta en producción.
Aviso
Esta guía se proporciona con fines informativos y se basa en la documentación API KSeF 2.0 y nuestras pruebas reales en el entorno TEST. Las especificaciones pueden cambiar. Consulte siempre la documentación oficial del Ministerio de Finanzas polaco para la información más reciente.