Skip to Content
v1.5Documentación oficial de la API LX CloudPos · estable en producción

Polling vs webhook

Hacienda demora segundos o minutos en resolver un comprobante. Existen dos formas de conocer el resultado: consultar repetidamente (polling) o recibir una notificación (webhook). La primera es simple, pero costosa y lenta; la segunda es la opción recomendada cuando es posible exponer un endpoint público.

Qué se reintenta y qué no

Conviene distinguir tres elementos que suelen confundirse en uno solo:

QuéReintento
Enviar el comprobante a Hacienda5 intentos, backoff de 10 s a 5 min
Consultar a Hacienda el estado finalcada 10 min, sin límite de tiempo, hasta que responda
Entregar el webhook al integrador3 intentos in-process (0 s / 2 s / 8 s) + 2 por cron cada 10 min

Las dos primeras corresponden a LX CloudPos frente a Hacienda; la tercera es la entrega hacia el integrador. Aun así, GET /api/v1/facturas/{clave} es siempre la fuente de verdad del estado: lo alimenta el barrido de la segunda fila, con independencia de si el webhook fue entregado.

Patrón polling (no recomendado)

Se consulta el detalle del comprobante en bucle hasta que cambie de estado. Resulta útil para pruebas locales o cuando no es posible exponer un endpoint público.

async function esperarHacienda(clave, maxIntentos = 30) { for (let i = 0; i < maxIntentos; i++) { const { data } = await axios.get(`/api/v1/facturas/${clave}`); if (data.estadoHacienda === 'aceptado') return data; if (data.estadoHacienda === 'rechazado') throw new Error('Rechazado'); await sleep(30000); // 30s } throw new Error('Timeout esperando Hacienda'); }

Patrón webhook (recomendado)

El comprobante se emite y no requiere seguimiento activo. LX CloudPos notifica cuando Hacienda responde y el integrador únicamente lee el resultado de su propia base de datos.

// 1. Emisor: emite y olvida await emitirFactura(data); // 2. Receptor webhook: marca el resultado app.post('/webhooks/lxs', verificarHmac, async (req, res) => { const evento = parsearEvento(req.body); await db.facturas.update({ where: { clave: evento.clave }, data: { estadoFinal: evento.ind_estado } }); res.status(200).end(); }); // 3. Frontend: consulta el estado de la BD propia, sin tocar la API