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

Idempotencia

Concepto

Si el sistema del integrador reintenta un POST /facturas por un timeout de red, sin idempotencia podrían generarse dos comprobantes para la misma operación, lo cual constituye una falla fiscal grave.

La idempotencia garantiza que un POST con la misma Idempotency-Key produce el mismo resultado, sin importar cuántas veces se reintente.

Uso

Debe enviarse un UUID único por operación de negocio en el header:

Idempotency-Key: 4f1c8a8a-2c4f-4b5e-9c2a-1234567890ab

Comportamiento

EscenarioRespuesta
Primera vez con esa keyProcesa normal. Cachea respuesta 24 h.
Reintento con misma key + mismo bodyDevuelve la respuesta cacheada (mismo status + body). No se re-emite.
Reintento con misma key + body distinto409 Conflict
Pasadas 24 hCache expira. Un POST con esa key vuelve a procesarse normal.

Reglas

La key debe generarse del lado del cliente, ANTES del primer intento. Debe usarse la misma key en todos los reintentos del mismo intento de negocio. Una key = una operación de negocio. No debe reutilizarse entre comprobantes distintos. Largo máximo: 100 caracteres. Formato recomendado: UUID v4.

Patrón correcto

async function emitir(facturaData, maxRetries = 3) { const idempotencyKey = crypto.randomUUID(); // ← una vez, fuera del loop for (let intento = 0; intento < maxRetries; intento++) { try { return await axios.post('/api/v1/facturas', facturaData, { headers: { 'X-Api-Key': process.env.LXS_API_KEY, 'Idempotency-Key': idempotencyKey // ← mismo valor en cada reintento }, timeout: 30000 }); } catch (err) { if (err.response?.status >= 500 || err.code === 'ECONNABORTED') { await sleep(2000 * (intento + 1)); continue; } throw err; } } throw new Error('Max retries excedidos'); }

Patrón incorrecto

// MAL: generamos la key dentro del loop → cada reintento crea factura distinta for (let i = 0; i < 3; i++) { await axios.post('/api/v1/facturas', data, { headers: { 'Idempotency-Key': crypto.randomUUID() } // ← bug! }); }