Rechazos y reintentos
Un rechazo de la DGII no siempre es definitivo. A veces el problema está en el propio comprobante y hay que emitir uno nuevo. Otras veces la DGII falla de forma pasajera, por ejemplo durante un mantenimiento, y basta con enviar de nuevo el mismo comprobante. NovaFE distingue ambos casos para que no tengas que hacerlo tú.
Qué indica un rechazo
Sección titulada «Qué indica un rechazo»Un comprobante rechazado queda con status: "rejected" y el motivo en
dgii.messages, una lista de objetos { code, value }. El campo
dgii.sequenceUsed responde la pregunta más importante: si la DGII
consumió el e-NCF.
dgii.sequenceUsed |
Significado |
|---|---|
false |
La DGII no consumió el e-NCF. El número sigue asociado a este comprobante y se puede reenviar. |
true o ausente |
La DGII consumió el e-NCF. Queda invalidado de forma permanente. |
Qué hace NovaFE en cada caso
Sección titulada «Qué hace NovaFE en cada caso»| Situación | Qué hace NovaFE | Qué haces tú |
|---|---|---|
| Falla pasajera de la DGII (por ejemplo, el código 004) y el número quedó libre | Reenvía el mismo comprobante por su cuenta, en intervalos. | Nada. Espera el resultado final por webhook. |
| Rechazo por otro motivo y el número quedó libre | Lo deja en rejected. |
Reenviarlo con POST /ecf/{id}/retry si lo consideras adecuado. |
| Rechazo con el número consumido | Lo deja en rejected. /retry responde 409. |
Emitir un comprobante nuevo, que recibirá otro e-NCF. |
Reintento automático
Sección titulada «Reintento automático»Cuando la DGII rechaza un comprobante y dice que no consumió el e-NCF, y
además el motivo es uno de los que NovaFE reconoce como falla pasajera de la
DGII, el comprobante no llega a quedar rejected. En su lugar:
- Vuelve a
signed. Endgii.messagespuedes ver el último motivo que informó la DGII mientras se espera el reenvío. - NovaFE lo reenvía más tarde, con el mismo XML, el mismo e-NCF, el mismo código de seguridad y el mismo QR. Por eso la representación impresa que ya hayas entregado sigue siendo válida.
- Si la DGII lo acepta, pasa a
acceptedcomo cualquier otro comprobante.
No se emite ecf.rejected mientras dure el reintento. Solo se emite si los
reintentos se agotan y el rechazo pasa a ser definitivo. En cambio, cada
reenvío que la DGII recibe emite de nuevo ecf.submitted, porque es una
recepción nueva.
Por defecto, NovaFE reintenta hasta 6 veces, esperando 2 minutos, 10 minutos, 30 minutos, 2 horas, 6 horas y 12 horas, unas 20 horas en total. Es tiempo suficiente para un mantenimiento largo de la DGII sin dejar un comprobante pendiente de forma indefinida.
Reenvío manual
Sección titulada «Reenvío manual»POST /api/v1/ecf/{id}/retryAcepta un comprobante en estado failed, review o rejected. En el caso
de rejected exige que la DGII haya dejado libre el e-NCF.
| Respuesta | Cuándo |
|---|---|
202 |
El comprobante volvió a signed y se reenviará. La respuesta trae el comprobante actualizado. |
404 |
El comprobante no existe o no es de tu tenant. |
409 |
El estado no admite reintento, o la DGII consumió el e-NCF de un comprobante rejected. |
Historial de envíos
Sección titulada «Historial de envíos»GET /api/v1/ecf/{id}/attempts devuelve un renglón por cada resultado que
la DGII dio para el comprobante, del más antiguo al más reciente. Es útil
porque el comprobante solo muestra el último resultado: sin el historial, un
rechazo anterior a un reenvío exitoso dejaría de verse.
[ { "attempt": 1, "outcome": "rejected", "trackId": "d64c95e4-69c3-4f6f-bd9b-cd3da8b9284f", "statusCode": 2, "statusText": "Rechazado", "sequenceUsed": false, "messages": [ { "code": 4, "value": "Ha ocurrido un error validando en eCF, favor intentar nueva vez." } ], "retryDecision": "auto:4", "xmlSha256": "3f8a1c9e2b7d4f60a5c8e1d2b3a4f5061c7e8d9f0a1b2c3d4e5f60718293a4b5", "recordedAt": "2026-09-25T15:32:42-04:00" }, { "attempt": 2, "outcome": "accepted", "trackId": "a12b34c5-6d7e-4f80-9a1b-2c3d4e5f6a7b", "statusCode": 1, "statusText": "Aceptado", "sequenceUsed": true, "messages": [], "retryDecision": null, "xmlSha256": "3f8a1c9e2b7d4f60a5c8e1d2b3a4f5061c7e8d9f0a1b2c3d4e5f60718293a4b5", "recordedAt": "2026-09-25T15:34:50-04:00" }]| Campo | Nota |
|---|---|
attempt |
1, 2, 3, dentro del comprobante. |
outcome |
El estado en que quedó el comprobante: accepted, accepted_conditional, rejected, review o failed. |
retryDecision |
En un rechazo: auto:<código> si NovaFE lo reenvió por su cuenta, o exhausted si era reintentable pero se agotaron los reintentos. Ausente en los demás. |
xmlSha256 |
Huella del XML enviado. Si dos renglones repiten el valor, se enviaron exactamente los mismos bytes. |
recordedAt |
Cuándo se registró el resultado. |
Un comprobante que aún no tiene ningún resultado devuelve una lista vacía. Los reintentos de transporte que no llegan a producir un resultado, como un tiempo de espera agotado, no generan renglón.
Recomendaciones
Sección titulada «Recomendaciones»- No emitas un comprobante nuevo ante un rechazo sin revisar
dgii.sequenceUsed. Si esfalse, el comprobante original todavía puede completarse. Emitir otro dejaría un e-NCF sin usar y un comprobante duplicado. - Suscríbete a los webhooks en lugar de consultar en bucle. Un rechazo
reintentable no genera
ecf.rejected, así que recibir ese evento indica que el resultado ya es definitivo. - Manda siempre
Idempotency-KeyenPOST /ecf(es obligatorio), para que un reintento de tu lado no emita dos comprobantes (ver Endpoints y semántica).