Límites de la API de KSeF: reintentos seguros en 2026

Conoce los límites actuales de la API de KSeF, cómo funcionan las ventanas móviles y cómo reintentar respuestas 429 sin duplicar facturas en producción.

Ernest Bursa

Ernest Bursa

Founder · · 13 min de lectura
Senior integration engineer monitoring three KSeF API quota windows and a paused invoice retry queue from a Warsaw operations desk

Esta traducción podría no estar actualizada. Ver en ingles

Los límites de peticiones de la API de KSeF se aplican a la vez por segundo, minuto y hora mediante ventanas móviles, normalmente para cada par (context, IP). Cuando KSeF devuelve un HTTP 429, espera el tiempo indicado por el servidor en Retry-After, pausa todos los workers que compartan esa cuota y concilia las referencias de sesión o factura guardadas antes de repetir un envío cuyo resultado no esté claro.

Esta última distinción es importante. Recibir un 429 te dice cuándo volver a intentarlo. Perder la conexión después de enviar una factura deja el resultado en el aire. Tratar ambos casos como un reintento genérico puede provocar envíos duplicados, bloqueos más largos y una cola que se vuelve menos estable a medida que aumenta la carga.

Esta es una guía técnica de operaciones, no asesoramiento fiscal ni jurídico. Los valores que figuran a continuación reflejan los contratos activos de KSeF comprobados el 28 de agosto de 2026.

¿Qué límites aplica KSeF a la API en producción?

KSeF asigna umbrales independientes por segundo, minuto y hora a distintos grupos de operaciones de la API. Los tres se aplican simultáneamente, de modo que el máximo por hora puede detener a un cliente que nunca supere el límite por segundo.

Cuando se hizo la comprobación, producción y DEMO ejecutaban la API 2.6.1. TEST usaba la 2.7.1, aunque los grupos de endpoints compartidos mantenían los mismos valores predeterminados. Estos son los límites que publica el contrato OpenAPI activo en producción:

Grupo de límites Operación representativa peticiones/s peticiones/min peticiones/h
onlineSession Abrir o cerrar una sesión en línea 10 30 120
batchSession Abrir o cerrar una sesión por lotes 10 20 60
invoiceSend Enviar una factura en una sesión en línea 10 30 180
invoiceStatus Consultar el estado de una factura 30 120 1 200
sessionList Listar sesiones 5 10 60
sessionInvoiceList Listar las facturas de una sesión o las facturas fallidas 10 20 200
sessionMisc Otras operaciones de sesión, factura y UPO 10 120 1 200
invoiceMetadata Consultar metadatos de facturas 8 16 20
invoiceExport Iniciar una exportación de facturas 8 16 20
invoiceExportStatus Consultar el estado de una exportación 10 60 600
invoiceDownload Descargar una factura por su número KSeF 8 16 64
other Cada uno de los demás recursos protegidos 10 30 120

Estos son valores predeterminados, no una constante de configuración que debas copiar para siempre en tu aplicación. El endpoint autenticado GET /rate-limits devuelve los valores efectivos del contexto actual. KSeF puede ajustar los límites, conceder un aumento individual o retirar más adelante un aumento temporal para restablecer el valor predeterminado. El aviso para integradores de abril de 2026 del Ministerio señala que los cambios individuales se aplican a DEMO y a producción a la vez.

Utiliza la tabla estática para planificar la capacidad. Usa GET /rate-limits para definir la política en tiempo de ejecución, guarda el resultado en caché y considera un 429 real como la autoridad definitiva.

Dos cifras obsoletas que debes quitar de los manuales antiguos

Primero, TEST ya no dispone de límites predeterminados diez veces superiores a los de producción. La API 2.5.0 igualó TEST y producción para los grupos compartidos, pero conservó endpoints exclusivos de TEST con los que los integradores pueden simular perfiles personalizados. La antigua afirmación del factor 10 todavía aparece en la guía de límites, aunque el registro de cambios de la API y los contratos activos reflejan la modificación posterior.

Segundo, un PDF oficial todavía fija la exportación de facturas en 4 peticiones por segundo y 8 por minuto. La API 2.4.0 elevó esos umbrales a 8 y 16 en producción el 16 de abril de 2026. El límite por hora se mantuvo en 20.

Aquí es fundamental tener en cuenta la versión. La rama main del repositorio ya incluye cambios de la API 2.7.1 que llegaron a TEST el 26 de agosto, pero cuyo despliegue en producción estaba previsto para el 23 de septiembre. Para saber cómo se comporta hoy el entorno de producción, el contrato OpenAPI de producción prevalece sobre una entrada futura de main.

¿Cómo contabiliza KSeF las peticiones?

Las peticiones protegidas se contabilizan normalmente para cada combinación de contexto KSeF e IP de origen. Los contadores emplean ventanas móviles, no minutos u horas fijos del reloj.

La guía oficial de límites de peticiones define la clave de cuota como el par formado por:

  • el ContextIdentifier empleado durante la autenticación, como Nip, InternalId o NipVatUe;
  • la dirección IP pública desde la que se conecta el cliente.

El mismo NIP utilizado a través de una única IP de salida comparte un presupuesto entre todos los procesos y workers que hay detrás de esa dirección. Otra oficina u otro integrador que emplee el mismo contexto desde una IP distinta recibe un contador independiente. Los endpoints públicos se protegen por IP.

Cada petición cuenta dentro del segundo, los 60 segundos y los 60 minutos anteriores. La ventana de un minuto no se reinicia a las 12:01:00, ni la de una hora cuando el reloj marca una hora en punto. Si consumes durante los diez primeros minutos las 20 exportaciones de facturas disponibles por hora, no basta con esperar a la siguiente hora en punto. Recuperas capacidad a medida que esas llamadas salen de la ventana móvil de 60 minutos.

Esto también explica por qué no basta con pausar cada proceso por separado. Diez workers de la aplicación pueden creer que están por debajo del límite y superar, con su tráfico combinado, el presupuesto compartido de (context, IP). El limitador debe coordinar todos los workers que usen la misma clave de cuota y el mismo grupo de límites.

No utilices la rotación de IP para esquivar los límites. El Ministerio indica expresamente que registra las infracciones y vigila el uso sistemático de varias direcciones para eludirlos. Los patrones repetidos o extremos pueden activar una protección más amplia para una entidad o un rango de IP.

¿Qué debe hacer tu integración tras un HTTP 429?

Ante un 429 Too Many Requests, lee Retry-After, deja de enviar peticiones del grupo de cuota afectado y espera al menos el número de segundos indicado. Puedes añadir un pequeño jitter positivo después de la espera exigida por el servidor, nunca en lugar de ella.

KSeF devuelve Retry-After como un número entero de segundos. El bloqueo es dinámico y las infracciones repetidas pueden alargarlo de forma considerable. No existe ningún valor fijo correcto para usar como alternativa, como «reintentar siempre al cabo de 30 segundos».

Un planificador seguro sigue esta secuencia:

quota_key = [context_identifier, egress_ip, limit_group]

on HTTP 429:
  retry_after = parse Retry-After as seconds
  pause quota_key until monotonic_now + retry_after
  requeue the operation after pause_until + small_positive_jitter
  record the attempt and stop after a bounded retry/time budget

La pausa compartida es importante. Si solo vuelves a poner en cola al worker que recibió la respuesta, los demás seguirán golpeando la misma cuota. Añadir jitter también es una decisión de ingeniería del cliente, no una exigencia del Ministerio. Sirve para repartir el arranque de los workers que estaban esperando tras la demora obligatoria y evitar que todos despierten en el mismo milisegundo.

KSeF admite dos formatos para el cuerpo de los errores. La respuesta JSON antigua sigue disponible. Los clientes pueden solicitar Problem Details con X-Error-Format: problem-details. En ambos casos, el calendario de reintentos procede de la cabecera de respuesta, así que tu capa HTTP debe conservar las cabeceras incluso cuando convierta el cuerpo en una excepción tipada.

El cliente oficial de C# analiza Retry-After y expone una espera recomendada. Su repositorio también incluye un componente de control de límites que consulta los valores efectivos, regula de antemano las tres ventanas y reintenta un 429 hasta cinco veces. Ese componente forma parte de las utilidades de prueba, no del flujo del SDK en producción. El SDK de Java también expone el error y las cabeceras, pero no instala un bucle genérico de reintentos automáticos.

Ambos clientes incluyen un circuit breaker que se abre tras cinco fallos transitorios consecutivos y permite una petición de prueba en estado semiabierto al cabo de 30 segundos. Un circuit breaker no es una política de reintentos. Hace que las peticiones fallen de inmediato para proteger la aplicación y KSeF; no repite por ti la petición fallida.

¿Qué errores debes reintentar, conciliar o detener?

Clasifica el resultado antes de reintentar. Un límite de peticiones, una tarea asíncrona pendiente, una entrada no válida y un resultado de red desconocido requieren respuestas distintas.

Resultado Qué significa Siguiente acción segura
HTTP 429 con Retry-After KSeF ha limitado la operación Pausa el grupo de cuota compartido, espera al menos el tiempo indicado y vuelve a intentarlo dentro de un presupuesto acotado de reintentos
Estado 100 o 150 La operación asíncrona se ha aceptado y sigue en curso Consulta el estado a un ritmo moderado y con jitter; no vuelvas a enviarla
HTTP 400 o fallo de validación de la factura La petición o el documento no son válidos Corrige la entrada; no reintentes la misma carga sin cambios
HTTP 401 o 403 La autenticación o autorización ha fallado Corrige las credenciales o los permisos antes de reintentar
HTTP 408, 5xx, tiempo de espera agotado o pérdida de conexión El fallo es transitorio, pero quizá se desconozca el resultado de una escritura Reintenta las lecturas seguras; concilia las escrituras antes de repetirlas
Estado terminal 550 KSeF ha cancelado el procesamiento e indica que se vuelva a intentar Conserva el registro de correlación anterior y crea después un reenvío controlado
Estado 440 KSeF ha detectado una factura duplicada Utiliza las referencias originales de sesión y KSeF para conciliar; no sigas reintentando

Esta tabla es deliberadamente más estricta que «reintentar todos los errores transitorios». Una petición GET que agota su tiempo de espera normalmente se puede repetir. En cambio, una petición POST que haya enviado bytes antes de perder la conexión quizá ya haya iniciado una operación asíncrona.

Aplica un límite de reintentos además de una espera. Una cola que reintenta indefinidamente oculta los incidentes y consume la capacidad que necesitan las tareas sanas. Cuando se agote el presupuesto de intentos o de tiempo, mueve la operación a un estado bloqueado y visible. Avisa también a un operador con los datos de correlación necesarios para continuar de forma segura.

¿Cómo se evitan los envíos duplicados de facturas?

La documentación no indica que el envío de facturas a KSeF sea idempotente. Guarda un intento local, el hash del contenido, la referencia de sesión y la referencia de la factura; después, concilia cualquier resultado incierto antes de crear otro envío.

El contrato de KSeF no expone ninguna cabecera Idempotency-Key ni un token de petición del cliente para enviar facturas. El hash SHA-256 de la factura sirve para comprobar su integridad y correlacionarla; no está documentado como clave de idempotencia.

Utiliza una máquina de estados local y persistente:

  1. Crea el intento antes de la petición. Guarda el ID de la factura de origen, el hash exacto del contenido enviado, el contexto, el entorno, el tipo de operación y el número de intento.
  2. Guarda las referencias de inmediato. Abrir una sesión en línea devuelve un referenceNumber de sesión. Enviar una factura devuelve un HTTP 202 con otro referenceNumber para la factura. Guarda cada uno antes de programar el siguiente paso.
  3. Distingue entre enviado y aceptado. Una respuesta HTTP correcta significa que KSeF ha aceptado la tarea para procesarla. Todavía no significa que la factura haya recibido un número KSeF.
  4. Concilia las escrituras inciertas. Si la respuesta se pierde, examina la sesión conocida, sus facturas y los hashes guardados. Si existe una referencia de factura, consulta su estado.
  5. Crea un intento nuevo solo después de conciliar. Conserva el intento anterior y explica por qué ha sido necesario repetir el envío.

La guía oficial sobre lotes recomienda expresamente mantener una correspondencia local entre el hash SHA-256 del XML original y su documento de origen. Los registros de facturas de sesión devueltos contienen el hash, la referencia, el número de factura, el estado y, si existe, el número KSeF. Así dispones de lo necesario para emparejar los resultados sin hacer suposiciones.

KSeF también detecta duplicados de forma global a partir del NIP del vendedor, el tipo de factura y su número. Un duplicado se convierte en el estado asíncrono 440, no en otro envío correcto. La respuesta correspondiente puede incluir originalSessionReferenceNumber y originalKsefNumber. Estos campos ayudan a reparar el estado cuando aparece un duplicado, pero no convierten la repetición en una operación idempotente.

¿Cómo debes dosificar las consultas de estado y el trabajo por lotes?

Asigna a cada grupo de límites de KSeF su propio canal coordinado, reserva margen por debajo de cada umbral móvil y prefiere las operaciones por lotes cuando haya más de una factura lista dentro de la misma ventana operativa.

Empieza con un limitador cuya clave sea (context, egress IP, limit group). Carga los valores efectivos desde GET /rate-limits, guárdalos en caché y actualízalos periódicamente. No consultes el endpoint de límites antes de cada petición, porque también es una operación de la API.

Después, separa estas cargas de trabajo:

  • control de sesiones en línea;
  • envíos interactivos de facturas;
  • consultas del estado de facturas;
  • creación de exportaciones y consultas de su estado;
  • descargas de facturas;
  • otras operaciones protegidas.

Mantén un margen deliberado. Un planificador que apunte exactamente a 30 envíos por minuto no deja espacio para el desfase del reloj, las tareas que despiertan tarde, otra instancia de la aplicación o el tráfico manual que emplea el mismo NIP y la misma IP.

Las consultas de estado merecen su propio presupuesto. Un endpoint de estado de factura permite 120 llamadas por minuto y 1 200 por hora, mientras que listar todas las sesiones solo admite 10 por minuto y 60 por hora. Consulta la referencia concreta que ya conoces en vez de listar todo una y otra vez. Aumenta progresivamente la espera mientras el estado sea 100 o 150, añade jitter, limita la demora y detente cuando obtengas un resultado terminal o venza el plazo operativo.

Para varias facturas, el Ministerio recomienda el modo por lotes. Un paquete con 100 facturas suele consumir la capacidad disponible con más eficiencia que 100 envíos interactivos. La subida de las partes del paquete dentro de una sesión por lotes abierta queda excluida de los límites de peticiones de la API y puede ejecutarse en paralelo, aunque abrir y cerrar la sesión siguen siendo operaciones limitadas.

El mismo principio se aplica a la consulta de datos. KSeF indica que los sistemas con gran volumen deben utilizar exportaciones asíncronas de facturas y sincronizarlas con una base de datos local. Llamar a KSeF cada vez que un usuario abre una factura convierte un repositorio central en la base de datos de la aplicación y desperdicia el ajustado presupuesto de descargas.

¿Qué debes monitorizar en producción?

Monitoriza el uso de las cuotas, las decisiones de reintento, los resultados asíncronos y el estado de recuperación sin registrar el contenido de las facturas ni las credenciales. Un simple recuento de respuestas 429 solo indica que el sistema llega tarde, no explica por qué.

Como mínimo, registra:

  • los límites efectivos y cuándo se actualizaron por última vez;
  • el número de peticiones por entorno, contexto, IP de salida y grupo de límites;
  • el número de respuestas 429, el valor de Retry-After, el número de intento y el resultado final;
  • la profundidad y la antigüedad de las colas de envíos, consultas de estado, exportaciones y descargas;
  • el tiempo transcurrido desde el envío hasta el estado terminal de la factura;
  • el número de estados pendientes 100/150, duplicados 440 y cancelados 550;
  • las escrituras con resultado desconocido pendientes de conciliación;
  • el estado del circuit breaker y las llamadas rechazadas;
  • las referencias de sesión, factura, exportación e intento local necesarias para prestar asistencia.

Mantén los campos sensibles fuera de los logs y los sistemas de seguimiento de errores. El XML de las facturas, los datos de compradores, los tokens de autenticación, los documentos UPO, las cookies y los parámetros sin filtrar de las peticiones no deben aparecer en un evento de excepción. Los identificadores, las transiciones de estado, la clase de respuesta, el ID de traza y los tiempos suelen bastar para diagnosticar un fallo de reintento.

Configura alertas sobre tendencias, no solo sobre respuestas aisladas. Una estimación creciente del consumo por hora, una cola de estados cada vez mayor o valores elevados y repetidos de Retry-After te dan margen para frenar a los productores antes de que la integración entre en una tormenta de reintentos.

¿Cómo gestiona hoy KSeF Kit los reintentos?

KSeF Kit emplea intentos de envío duraderos y referencias de KSeF almacenadas para poder reanudar las consultas sin volver a enviar a ciegas la misma factura. Su documentación pública describe cinco reintentos, con esperas crecientes, ante fallos transitorios 429, 500 y 550.

El ciclo de presentación parte de una factura de Stripe finalizada como fuente inmutable, la transforma a FA(3), abre una sesión en línea, la envía y consulta el estado hasta obtener el número KSeF y el UPO. Cada intento de envío es un registro independiente. Si la consulta se interrumpe, las referencias guardadas permiten que una tarea posterior continúe desde la operación aceptada.

La guía de la API de KSeF y el manual de actuación ante interrupciones distinguen los reintentos transitorios de la conciliación. Los estados visibles para el usuario separan las tareas en cola, en proceso de envío, aceptadas, rechazadas y bloqueadas. La documentación de seguridad indica que, en la versión alojada, los errores enviados a Sentry incluyen identificadores y el estado, pero excluyen el contenido de las facturas, los datos personales de los compradores, los tokens, los UPO, los parámetros de las peticiones y las cookies.

Ese es el alcance actual del producto. KSeF Kit no afirma públicamente que disponga de presupuestos de peticiones por contexto, una política de jitter documentada, paneles de límites o emisión offline24. La arquitectura más amplia de esta guía es el estándar al que debería aspirar una integración en producción, no una lista de funciones ocultas del producto.

La regla operativa es sencilla: regula el ritmo antes de que KSeF tenga que detenerte, respeta la espera cuando lo haga y no confundas nunca reintentar una petición tras un fallo de transporte con determinar si una factura llegó a existir.

¿Envías facturas de Stripe a KSeF? KSeF Kit transforma las facturas finalizadas en FA(3), registra cada intento y conserva la referencia KSeF y el UPO junto al registro de origen.

Empieza gratis

Artículos relacionados

¿Listo para contratar de forma más inteligente?

Empieza gratis durante 30 días. Cancela antes de que termine y no pagas nada. Configura tu primer pipeline de contratación en minutos.

Empieza gratis