Secuencias y fechas
Tres cosas producen la mayoría de los rechazos de la DGII, y ninguna de las tres da un mensaje que apunte a la causa: el número de comprobante, la fecha de vencimiento del rango y el formato de las fechas. Esta página es corta a propósito. Léela entera.
El e-NCF es tuyo, no de FiscalFlow
La DGII autoriza al contribuyente un rango de números por tipo de comprobante. FiscalFlow no reparte esos números: los usa como se los mandes. Quien lleva el contador es tu sistema.
El formato es E + los dos dígitos del tipo + diez dígitos de secuencia:
E310000000001
^^^^^
| | +-- secuencia, 10 dígitos
| +----- tipo (31)
+------- literal E
| Ambiente | Campo encf |
|---|---|
testecf |
Opcional. Si lo omites, FiscalFlow inventa uno para que puedas probar el flujo sin cargar secuencias. |
certecf y ecf |
Obligatorio. Sin el, el documento se rechaza de inmediato con error_code: ENCF_REQUIRED, sin llegar a la DGII y sin consumir nada. |
Un e-NCF se usa una sola vez, y la DGII lleva la cuenta por RNC, no por sistema.
Si el mismo RNC factura desde dos sistemas — tu ERP y un punto de venta, o FiscalFlow y una localización fiscal que ya estaba instalada — los dos avanzando sobre el mismo rango chocan, y el segundo recibe "Este número de secuencia ya ha sido utilizado". Reserva un bloque distinto para cada sistema. Un número quemado no se recupera.
FiscalFlow también rechaza por su cuenta un e-NCF repetido dentro de la misma empresa y ambiente,
antes de gastar la llamada a la DGII: recibes 409 con
error.code: DUPLICATE_DOCUMENT. Para ver qué números llevas emitidos por tipo:
/api/v1/companies/{uuid}/sequences
curl -H "X-API-Key: ffs_live_ejemplodeclavenoreal000000000000000000" \
https://api.fiscalflowsupport.com/api/v1/companies/9f1c2d3e-4b5a-6c7d-8e9f-0a1b2c3d4e5f/sequences
{
"success": true,
"data": [
{
"type": "31",
"type_label": "Factura Crédito Fiscal",
"last_encf": "E310000000042",
"total_accepted": 42,
"last_emitted_at": "2026-08-14T15:06:02+00:00"
},
{
"type": "32",
"type_label": "Factura de Consumo",
"last_encf": null,
"total_accepted": 0,
"last_emitted_at": null
}
]
}
expiration_date: la causa del rechazo 145
expiration_date se convierte en FechaVencimientoSecuencia dentro del
XML, y tiene que ser la fecha de vencimiento del rango de e-NCF que la DGII te
autorizó, tal como aparece en la Oficina Virtual. La DGII la valida contra la
autorización real. Cualquier otra fecha — aunque sea futura y perfectamente valida como
fecha — se rechaza con el código 145, "Fecha de vencimiento de secuencia
inválida", y el mensaje no menciona el campo.
| Tipo | expiration_date |
|---|---|
31 33 41 43 44 45 46 47 |
Obligatorio. Sin el, el documento se rechaza antes de firmarse, de forma permanente y sin reintentos, con una explicación de que configurar. |
32 y 34 |
Prohibido por sus esquemas. Si lo envías se ignora: el elemento no se escribe en el XML. |
expiration_date en dd-mm-yyyy. Desde 2.0.0 el
request lo valida contra ese formato y devuelve 422 si no cuadra, antes de crear el
documento: así un valor malo ya no te cuesta un e-NCF. Hasta 1.1.5 este campo viajaba al XML tal
cual lo escribías, así que un 2026-12-31 pasaba el request y moría después en el
esquema de la DGII con "El formato del XML no es valido", con la secuencia ya gastada.
Formato de fechas
Dentro del e-CF todas las fechas son dd-mm-yyyy. En el payload de la API la cosa se
divide, así que vale la pena tenerlo a mano:
| Campo | Formato a enviar | Nota |
|---|---|---|
emission_date |
yyyy-mm-dd |
Validado como ISO y convertido internamente. Si lo omites, se usa hoy. |
payment.due_date |
yyyy-mm-dd |
Igual. Obligatorio cuando payment.type es 2 (crédito). |
reference.date |
dd-mm-yyyy o yyyy-mm-dd |
Se normaliza. Antes viajaba en crudo y rompía las notas de crédito y débito; corregido en 1.1.4. |
expiration_date |
dd-mm-yyyy |
El request rechaza cualquier otro formato con 422. Antes viajaba en crudo; corregido en 2.0.0. |
Una fecha que no se pueda leer no se reintenta: el documento se rechaza de una vez con el mensaje "El campo {campo} no contiene una fecha valida". Es deliberado, reintentar lo mismo cinco veces no lo arregla.
Idempotencia con external_ref
external_ref es tu identificador del documento — el número de factura de tu
sistema, por ejemplo. Es único por organización y es lo que evita que un timeout de red o un
reintento de tu cliente HTTP consuman un segundo e-NCF.
Si envías dos veces el mismo external_ref, la segunda llamada devuelve
200 con el documento que ya existe y "duplicate": true. No se crea
nada, no se emite nada:
{
"success": true,
"duplicate": true,
"data": {
"id": "01jz8k4qm2n5p7r9t1v3w5x7y9",
"external_ref": "venta-2026-000412",
"status": "accepted",
"encf": "E310000000001"
},
"exec_time_ms": 12
}
external_ref no hay protección: dos POST idénticos crean dos documentos y
consumen dos números. Mándalo siempre.
Corregir un documento rechazado
Cuando la DGII rechaza por un dato malo, el número ya suele estar quemado. El flujo correcto es descartar y reenviar corregido, no reintentar.
-
Mira
sequence_consumed. Si esfalse, el número sigue libre y basta conPOST /api/v1/documents/{id}/retry. Si estrue, sigue leyendo. -
Descarta el documento rechazado. Esto libera el e-NCF para poder volver a presentarlo con
datos corregidos:
curl -X POST \ -H "X-API-Key: ffs_live_ejemplodeclavenoreal000000000000000000" \ -H "Content-Type: application/json" \ -d '{"reason": "Fecha de vencimiento de secuencia corregida"}' \ https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/discard -
Envía el documento corregido con un
external_refdistinto. El del documento descartado queda reservado para siempre; reutilizarlo devuelve el documento descartado en vez de emitir. Una convención que funciona bien es sufijar el intento:venta-2026-000412,venta-2026-000412-r2.
Solo se puede descartar un documento en estado rejected. Sobre cualquier otro
estado, la respuesta es 422 con error.code: INVALID_DOCUMENT_STATE.