Ciclo de vida de un e-CF
Enviar un e-CF y saber si la DGII lo acepto son dos eventos distintos, separados en el tiempo. Esta página describe el ciclo completo. Si solo lees una página de conceptos antes de integrar, que sea esta.
Los estados
| status | Terminal | Significado |
|---|---|---|
processing |
No | El documento existe en FiscalFlow y está en camino a la DGII, o ya llegó y la DGII todavía no resuelve. Es el estado con el que nace todo documento. |
accepted |
Si | La DGII lo acepto. El e-CF tiene validez fiscal, el PDF y el XML firmado están disponibles. |
rejected |
Si | Rechazado. error_message trae el motivo, casi siempre en las palabras exactas de la DGII. Ver Errores y rechazos. |
accepted_conditional |
Si | Aceptado con observaciones. Se trata como autorizado en todo el sistema. Hoy la respuesta de la DGII se normaliza a accepted, así que en la práctica no lo verás; el valor existe para no romper clientes si eso cambia. |
cancelled |
Si | Anulado. Ver Anular un e-CF. |
draft |
No | Valor por defecto de la base de datos. Ningun documento creado por la API llega a tus manos en este estado. |
La respuesta de cualquier documento trae además dos campos derivados que suelen ser más comodos
que comparar status a mano: authorized (booleano, verdadero para
accepted y accepted_conditional) y legal_status.
El camino normal: asíncrono
Al recibir POST /v1/documents, FiscalFlow arma el XML, lo firma y lo transmite a la
DGII dentro de la misma petición. Lo que la DGII devuelve ahí no es un veredicto: es un acuse
con un trackId. El documento queda en processing y la respuesta HTTP es
202 Accepted.
{
"success": true,
"data": {
"id": "01jz8k4qm2n5p7r9t1v3w5x7y9",
"external_ref": "venta-2026-000412",
"type": "31",
"type_label": "Factura Crédito Fiscal",
"encf": "E310000000001",
"status": "processing",
"legal_status": null,
"authorized": false,
"authorization_number": "4A8F2C1E9B",
"environment": "testecf",
"track_id": "4A8F2C1E9B",
"totals": { "subtotal": 5000, "exempt_amount": 0, "itbis": 900, "total": 5900 },
"currency": "DOP",
"buyer_rnc": "101000001",
"buyer_name": "Cliente de Prueba SRL",
"error_message": null,
"error_code": null,
"sequence_consumed": true,
"attempts": 0,
"_links": {
"self": "https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9",
"xml": "https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/xml",
"pdf": "https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/pdf",
"qr": "https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/qr",
"notify": "https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/notify"
},
"emitted_at": "2026-08-14T15:04:11+00:00",
"accepted_at": null,
"created_at": "2026-08-14T15:04:10+00:00",
"updated_at": "2026-08-14T15:04:11+00:00"
},
"exec_time_ms": 1840,
"message": "Document is still being processed."
}
202 no es un error y no es un rechazo. Significa que el documento está en manos
de la DGII y su veredicto llegara después. Guarda el id y sigue adelante.
La excepción: el canal RFCE responde de inmediato
Las facturas de consumo E32 con total menor a RD$250,000 viajan por el canal de
resumen B2C (RFCE), que devuelve el veredicto en la misma respuesta HTTP. En ese caso el
documento ya llega terminal y la respuesta es 200 OK con
status en accepted o rejected.
Es estrictamente menor: una E32 de exactamente RD$250,000.00 va por el canal normal y es asíncrona. Ningun otro tipo usa RFCE.
Como te enteras del veredicto
Tres mecanismos, de menos a más trabajo de tu parte.
1. Webhooks (recomendado)
Suscríbete al evento document.emission.completed. FiscalFlow te llama en cuanto el
documento llega a un estado terminal, venga de la respuesta inmediata de la DGII o de la
consulta posterior. Ver Webhooks.
2. Consulta puntual
POST /v1/documents/{id}/refresh-status le pregunta a la DGII ahora mismo por el
veredicto de un documento que sigue en processing. Es la acción detras del boton
"actualizar estado" de una interfaz.
/api/v1/documents/{id}/refresh-status
curl -X POST \
-H "X-API-Key: ffs_test_ejemplodeclavenoreal000000000000000000" \
https://api.fiscalflowsupport.com/api/v1/documents/01jz8k4qm2n5p7r9t1v3w5x7y9/refresh-status
import requests
doc_id = "01jz8k4qm2n5p7r9t1v3w5x7y9"
r = requests.post(
f"https://api.fiscalflowsupport.com/api/v1/documents/{doc_id}/refresh-status",
headers={"X-API-Key": "ffs_test_ejemplodeclavenoreal000000000000000000"},
)
body = r.json()
print(body["data"]["status"], body["changed"])
{
"success": true,
"data": { "status": "accepted", "accepted_at": "2026-08-14T15:06:02+00:00" },
"changed": true,
"message": "Status updated from the DGII: accepted."
}
changed te dice si esta consulta movió el estado. Si la DGII todavía no resuelve,
devuelve changed: false y el documento sigue en processing: no es un error.
3. Reconciliación automática
Aunque no hagas nada, FiscalFlow consulta por su cuenta cada cinco minutos el veredicto de todo
documento que siga en processing y tenga track_id. Cuando resuelve,
actualiza el documento y dispara el webhook. Es la red de seguridad: si tu webhook estaba caído
y no sondeas, el estado se corrige solo y lo verás al consultar el documento.
Reintentos ante fallos de transporte
Si la DGII no responde, responde con un 5xx o hay un fallo de red, el envío se reintenta solo
con espera creciente: 1 minuto, 5, 15, 1 hora y 6 horas. A los cinco intentos el documento
queda en rejected con error_message empezando por
Max attempts reached.. El campo attempts de la respuesta te dice en
que intento va.
Los errores de contenido no se reintentan. Si el XML no cumple el esquema de la DGII, o
falta un dato obligatorio como expiration_date, o una fecha es ilegible, el
documento se rechaza de inmediato con error_code igual a
XSD_VALIDATION_FAILED y no se vuelve a intentar: reintentarlo daría exactamente el
mismo resultado. Corrige el dato y envía un documento nuevo.
Qué hacer con un documento rechazado
Depende de si la DGII consumió el número. El campo sequence_consumed lo dice.
-
sequence_consumed: false— el e-NCF sigue libre. Puedes reenviar el mismo documento conPOST /v1/documents/{id}/retry. -
sequence_consumed: true— la DGII ya quemó ese número. Reenviarlo solo produce "Este número de secuencia ya ha sido utilizado". Hay que descartar el documento y enviar uno nuevo con el siguiente e-NCF.
El flujo de corrección completo, con ejemplos, esta en Secuencias y fechas.
Resumen del flujo
POST /api/v1/documents
|
+-- E32 < RD$250,000 --> 200 OK, status accepted | rejected (fin)
|
+-- todo lo demás --> 202 Accepted, status processing
|
+-- webhook document.emission.completed
+-- POST /documents/{id}/refresh-status
+-- reconciliación cada 5 minutos
|
v
accepted | rejected