📖
KSeF API 2.0

Guía API KSeF 2.0

Referencia técnica completa para la integración con la API KSeF del Ministerio de Finanzas polaco

Probar mis facturas

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.

EntornoURLPropósito
TESThttps://api-test.ksef.mf.gov.pl/v2Pruebas libres, NIPs ficticios
DEMOhttps://api-demo.ksef.mf.gov.pl/v2Demostración
PRODhttps://api.ksef.mf.gov.pl/v2Producció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 → accessToken

Headers requeridos para llamadas autenticadas

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

Claves públicas

GET /security/public-key-certificates devuelve 2 certificados:

UsageUso
KsefTokenEncryptionCifrado del token durante la autenticación
SymmetricKeyEncryptionCifrado 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 session

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

Apertura 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": "..."
  }
}
CampoValor
batchFile.fileSizeTamaño del ZIP antes del cifrado
batchFile.fileHashSHA256 del ZIP antes del cifrado
fileParts[].fileSizeTamaño del ZIP después del cifrado
fileParts[].fileHashSHA256 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)

CodeSignificado
100Proceso registrado / aceptado para procesamiento
150Procesamiento en curso (reemplaza el antiguo código 300 desde RC3)
170Procesamiento completado
200Éxito → ksefNumber disponible, sesión procesada, exportación completada
210Exportación expirada, ya no disponible para descarga

Errores (400-550)

CodeSignificado
400Operación fallida, solicitud rechazada
405Error de verificación de paquete (sanity check) / error de sesión
410Identificadores inconsistentes, alcance de permisos inválido
415Permisos faltantes, error de descifrado de clave, adjuntos no permitidos
420Filtros demasiado amplios, límite de facturas excedido, permiso denegado
425Token invalidado / hash de archivo inválido
429Rate limit excedido (~100/s, ~300/min, ~1200/h)
430Error de descompresión, error de verificación de factura, rol faltante
435Error de descifrado de archivo (cifrado incorrecto)
440Sesión cancelada (timeout de upload), factura duplicada, operación prohibida
441Error de verificación del subproceso de procesamiento de factura
445Error de finalización, ninguna factura válida encontrada
450Token inválido, error de estructura de factura, XML inválido
460Fallo de certificado (inválido, cadena no confiable, revocado)
470Intento de uso de métodos de autorización de una persona fallecida
480Auth bloqueada: sospecha de incidente de seguridad (contactar MF vía formulario)
500Error de servidor desconocido
550Operación cancelada por el sistema (atómica, sin procesamiento parcial). Reintentar.

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

6. Límites

ParámetroValor
Tamaño máx. factura sin adjuntos1 MB
Tamaño máx. factura con adjuntos3 MB (configurable hasta 10 MB)
Máx. facturas por sesión batch10 000 000
Tamaño máx. ZIP5 GB
Máx. partes por ZIP50 (100 MB cada una)
Timeout de sesión batch no cerrada12h → cancelación automática (código 440)

Verificable vía GET /limits/context.

7. Adjuntos (Zalacznik)

Prerrequisitos

  • 1.Activación : POST /testdata/attachment con {"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

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 (entorno TEST)

No requiere autenticación. Estos endpoints permiten configurar el entorno de prueba.

EndpointMétodoEstadoNotes
/testdata/subjectPOSTOK{"subjectNip": "...", "description": "..."}
/testdata/personPOSTOK{"nip": "...", "pesel": "...", "description": "..."}
/testdata/attachmentPOSTOK{"nip": "..."} — activa los adjuntos
/testdata/attachment/revokePOSTOK{"nip": "..."} — revocación no inmediata
/testdata/permissionsPOST500Roto desde el lanzamiento de KSeF 2.0

9. Endpoints de información

Endpoints autenticados para consultar el estado de su cuenta y facturas.

EndpointDescription
/permissions/attachments/statusEstado de autorización de adjuntos
/limits/contextLímites de sesión (tamaño máx., etc.)
/rate-limitsRate limits actuales
/auth/sessionsSesiones activas
/invoices/query/metadataBú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:

ProblemaSourceDetalles
POST /testdata/permissions devuelve 500#296Roto 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 inmediataPruebas 04/02/2026Tras llamar a /testdata/attachment/revoke, isAttachmentAllowed permanece en true con un revokedDate futuro.
Servidor TEST lento (código 150 prolongado)#408, #278Tras 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)#674No es un bug: los adjuntos requieren una sesión batch. El modo online devuelve 415.

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