Valida un comprobante sin emitirlo
const url = 'https://api.novafe.example/api/v1/ecf/validate';const options = { method: 'POST', headers: {'X-API-Key': '<X-API-Key>', 'Content-Type': 'application/json'}, body: '{"type":31,"encf":"example","sequenceExpiresOn":"2026-04-15","issueDate":"2026-04-15","incomeType":"example","pricesIncludeTax":true,"deferredDelivery":true,"nonInvoiceableAmount":1,"internalNumber":"example","sellerCode":"example","additionalInfo":{"issuer":"example","buyer":"example"},"buyer":{"name":"example","rnc":"example","foreignId":"example","email":"example","contact":"example","address":"example","municipality":"example","province":"example","additionalInfo":"example"},"payment":{"condition":"example","dueDate":"2026-04-15","methods":[{"type":"example","amount":1}]},"lines":[{"name":"example","kind":"example","quantity":1,"unitPrice":1,"itbisRate":1,"unitOfMeasure":"example","description":"example","discount":0,"surcharge":0,"priceIncludesTax":true,"declaredAmount":1,"codes":[{"type":"example","value":"example"}],"retention":{"agent":"withholding","itbisWithheld":0,"isrWithheld":0},"additionalTaxes":[{"code":"example","rate":0,"iscEspecifico":0,"iscAdvalorem":0,"otros":0}],"foreignCurrency":{"unitPrice":1,"discount":1,"surcharge":1,"lineAmount":1},"details":{"referenceQuantity":1,"referenceUnit":"example","subquantities":[{"quantity":1,"unitCode":"example"}],"alcoholDegrees":1,"referenceUnitPrice":1,"manufactureDate":"2026-04-15","expiryDate":"2026-04-15","mining":{"netWeightKilogram":1,"netWeightMining":1,"affiliationType":1,"settlement":1}}}],"reference":{"modifiedNcf":"example","modifiedNcfDate":"2026-04-15","modificationCode":"example","otherIssuerRnc":"example"},"globalAdjustments":[{"line":1,"kind":"discount","affectsItbisRate":1,"amount":0,"norm1007":false,"description":"example","percentage":1}],"foreignCurrency":{"currency":"example","exchangeRate":1,"totals":{"montoGravadoTotal":1,"montoGravadoI1":1,"montoGravadoI2":1,"montoGravadoI3":1,"montoExento":1,"totalItbis":1,"totalItbis1":1,"totalItbis2":1,"totalItbis3":1,"montoTotal":1}},"shipping":{"shipmentDate":"2026-04-15","shipmentNumber":"example","containerNumber":"example","referenceNumber":"example","grossWeight":1,"netWeight":1,"grossWeightUnit":"example","netWeightUnit":"example","packageCount":1,"packageUnit":"example","volume":1,"volumeUnit":"example","export":{"loadingPortName":"example","deliveryTerms":"example","totalFob":1,"insurance":1,"freight":1,"otherCharges":1,"totalCif":1,"customsRegime":"example","departurePortName":"example","unloadingPortName":"example"}},"transport":{"driver":"example","transportDocument":"example","vehicleId":"example","plate":"example","route":"example","zone":"example","deliveryNote":"example","via":"example","originCountry":"example","destinationAddress":"example","destinationCountry":"example","carrierRnc":"example","carrierName":"example","voyageNumber":"example"},"subtotals":[{"number":1,"description":"example","order":1,"montoGravadoTotal":1,"montoGravadoI1":1,"montoGravadoI2":1,"montoGravadoI3":1,"totalItbis":1,"itbis1":1,"itbis2":1,"itbis3":1,"montoImpuestoAdicional":1,"montoExento":1,"amount":1,"lines":1}],"pagination":[{"number":1,"lineFrom":1,"lineTo":1,"montoGravadoTotal":1,"montoGravadoI1":1,"montoGravadoI2":1,"montoGravadoI3":1,"montoExento":1,"totalItbis":1,"itbis1":1,"itbis2":1,"itbis3":1,"montoImpuestoAdicional":1,"iscEspecifico":1,"otrosImpuestos":1,"amount":1,"nonInvoiceableAmount":1}],"declaredTotals":{"montoGravadoTotal":1,"montoExento":1,"totalItbis":1,"montoImpuestoAdicional":1,"montoTotal":1}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.novafe.example/api/v1/ecf/validate \ --header 'Content-Type: application/json' \ --header 'X-API-Key: <X-API-Key>' \ --data '{ "type": 31, "encf": "example", "sequenceExpiresOn": "2026-04-15", "issueDate": "2026-04-15", "incomeType": "example", "pricesIncludeTax": true, "deferredDelivery": true, "nonInvoiceableAmount": 1, "internalNumber": "example", "sellerCode": "example", "additionalInfo": { "issuer": "example", "buyer": "example" }, "buyer": { "name": "example", "rnc": "example", "foreignId": "example", "email": "example", "contact": "example", "address": "example", "municipality": "example", "province": "example", "additionalInfo": "example" }, "payment": { "condition": "example", "dueDate": "2026-04-15", "methods": [ { "type": "example", "amount": 1 } ] }, "lines": [ { "name": "example", "kind": "example", "quantity": 1, "unitPrice": 1, "itbisRate": 1, "unitOfMeasure": "example", "description": "example", "discount": 0, "surcharge": 0, "priceIncludesTax": true, "declaredAmount": 1, "codes": [ { "type": "example", "value": "example" } ], "retention": { "agent": "withholding", "itbisWithheld": 0, "isrWithheld": 0 }, "additionalTaxes": [ { "code": "example", "rate": 0, "iscEspecifico": 0, "iscAdvalorem": 0, "otros": 0 } ], "foreignCurrency": { "unitPrice": 1, "discount": 1, "surcharge": 1, "lineAmount": 1 }, "details": { "referenceQuantity": 1, "referenceUnit": "example", "subquantities": [ { "quantity": 1, "unitCode": "example" } ], "alcoholDegrees": 1, "referenceUnitPrice": 1, "manufactureDate": "2026-04-15", "expiryDate": "2026-04-15", "mining": { "netWeightKilogram": 1, "netWeightMining": 1, "affiliationType": 1, "settlement": 1 } } } ], "reference": { "modifiedNcf": "example", "modifiedNcfDate": "2026-04-15", "modificationCode": "example", "otherIssuerRnc": "example" }, "globalAdjustments": [ { "line": 1, "kind": "discount", "affectsItbisRate": 1, "amount": 0, "norm1007": false, "description": "example", "percentage": 1 } ], "foreignCurrency": { "currency": "example", "exchangeRate": 1, "totals": { "montoGravadoTotal": 1, "montoGravadoI1": 1, "montoGravadoI2": 1, "montoGravadoI3": 1, "montoExento": 1, "totalItbis": 1, "totalItbis1": 1, "totalItbis2": 1, "totalItbis3": 1, "montoTotal": 1 } }, "shipping": { "shipmentDate": "2026-04-15", "shipmentNumber": "example", "containerNumber": "example", "referenceNumber": "example", "grossWeight": 1, "netWeight": 1, "grossWeightUnit": "example", "netWeightUnit": "example", "packageCount": 1, "packageUnit": "example", "volume": 1, "volumeUnit": "example", "export": { "loadingPortName": "example", "deliveryTerms": "example", "totalFob": 1, "insurance": 1, "freight": 1, "otherCharges": 1, "totalCif": 1, "customsRegime": "example", "departurePortName": "example", "unloadingPortName": "example" } }, "transport": { "driver": "example", "transportDocument": "example", "vehicleId": "example", "plate": "example", "route": "example", "zone": "example", "deliveryNote": "example", "via": "example", "originCountry": "example", "destinationAddress": "example", "destinationCountry": "example", "carrierRnc": "example", "carrierName": "example", "voyageNumber": "example" }, "subtotals": [ { "number": 1, "description": "example", "order": 1, "montoGravadoTotal": 1, "montoGravadoI1": 1, "montoGravadoI2": 1, "montoGravadoI3": 1, "totalItbis": 1, "itbis1": 1, "itbis2": 1, "itbis3": 1, "montoImpuestoAdicional": 1, "montoExento": 1, "amount": 1, "lines": 1 } ], "pagination": [ { "number": 1, "lineFrom": 1, "lineTo": 1, "montoGravadoTotal": 1, "montoGravadoI1": 1, "montoGravadoI2": 1, "montoGravadoI3": 1, "montoExento": 1, "totalItbis": 1, "itbis1": 1, "itbis2": 1, "itbis3": 1, "montoImpuestoAdicional": 1, "iscEspecifico": 1, "otrosImpuestos": 1, "amount": 1, "nonInvoiceableAmount": 1 } ], "declaredTotals": { "montoGravadoTotal": 1, "montoExento": 1, "totalItbis": 1, "montoImpuestoAdicional": 1, "montoTotal": 1 } }'Corre la misma matriz de validación
estructural y fiscal por tipo (Módulo 2 + 6) que POST /ecf, pero no
asigna una secuencia real, no firma y no persiste nada. Responde 200
siempre que pueda evaluar el comprobante: valid dice si pasa,
errors trae todos los problemas (no solo el primero), warnings
los avisos que no impiden emitir y preview los totales calculados y un
e-NCF de muestra (nunca uno real), solo si es válido. Un cuerpo ilegible, una
petición sin autenticar o un emisor sin perfil configurado siguen siendo
errores HTTP, porque ahí no hay nada que evaluar.
Autenticación: requiere una API key (header X-API-Key) con rol admin_tenant o emisor.
Authorizations
Sección titulada «Authorizations»Request Bodyrequired
Sección titulada «Request Bodyrequired»Payload de emisión de un e-CF (POST /api/v1/ecf). Un solo objeto
discriminado por int IssueEcfCommand.Type; el servidor asigna la secuencia, arma el
bloque Emisor desde el perfil del tenant, calcula los totales, firma y persiste.
object
Código DGII del tipo de e-CF: 31, 32, 33, 34, 41, 43, 44, 45, 46, 47.
E-NCF de 13 caracteres. Solo con sequences.mode = external (y
obligatorio ahí); con managed se rechaza, NovaFE asigna el suyo.
<FechaVencimientoSecuencia> del e-NCF. Con
sequences.mode = external es obligatorio en los tipos que llevan
vencimiento (todos menos 32 y 34) y no aplica en esos dos; en
managed se rechaza.
Fecha de emisión (calendario dominicano). Default: hoy.
<TipoIngresos> — “01”…“06”. Obligatorio en 31/32/33/34/44/45/46.
true si los precios de las líneas ya traen el ITBIS incluido.
<IndicadorEnvioDiferido> — solo contribuyentes autorizados.
<MontoNoFacturable> — reembolsos, propina voluntaria. Puede ser negativo.
<NumeroFacturaInterna> — clave de dedup de negocio.
<CodigoVendedor>.
Bloque de pago del encabezado.
object
Una forma de pago. Type y Amount son nullable para distinguir “no vino” de un
valor: el validador exige ambos y la API nunca rellena uno por su cuenta.
object
Una línea de <DetallesItems>.
object
object
Desglose de impuestos adicionales por código de la Tabla I (001–039). Todos los
montos los trae el cliente ya calculados. iscEspecifico (monto fijo por
volumen: alcoholes 006-018, cigarrillos 019-022) integra la base imponible
del ITBIS de esa línea; iscAdvalorem y otros (Propina, CDT, ISC
de servicios, Primera Placa…) van “por encima”, sin tocar la base.
object
Campos opcionales del <Item> — passthrough. La derivación del
ISC desde alcoholDegrees/referenceQuantity es un slice posterior;
hoy el cliente trae el monto final del ISC en additionalTaxes (el ISC
específico ahí sí integra la base del ITBIS — ver EcfAdditionalTaxPayload).
object
object
<Mineria> — datos de liquidación minera (solo tipos 32/33/34/46).
object
Un descuento o recargo global (Sección D).
object
Facturación en divisa (<OtraMoneda>). El cliente trae los montos ya convertidos.
object
object
Datos de embarque (<InformacionesAdicionales>). Passthrough.
object
Datos de exportación (solo tipo 46).
object
Datos de transporte (<Transporte>). Passthrough.
object
Subtotal informativo para la RI (Sección C). No afecta la base imponible.
object
Página de la RI (<Paginacion>).
object
Totales declarados por el cliente (chequeo de tolerancia; nunca bloquea).
object
Payload de emisión de un e-CF (POST /api/v1/ecf). Un solo objeto
discriminado por int IssueEcfCommand.Type; el servidor asigna la secuencia, arma el
bloque Emisor desde el perfil del tenant, calcula los totales, firma y persiste.
object
Código DGII del tipo de e-CF: 31, 32, 33, 34, 41, 43, 44, 45, 46, 47.
E-NCF de 13 caracteres. Solo con sequences.mode = external (y
obligatorio ahí); con managed se rechaza, NovaFE asigna el suyo.
<FechaVencimientoSecuencia> del e-NCF. Con
sequences.mode = external es obligatorio en los tipos que llevan
vencimiento (todos menos 32 y 34) y no aplica en esos dos; en
managed se rechaza.
Fecha de emisión (calendario dominicano). Default: hoy.
<TipoIngresos> — “01”…“06”. Obligatorio en 31/32/33/34/44/45/46.
true si los precios de las líneas ya traen el ITBIS incluido.
<IndicadorEnvioDiferido> — solo contribuyentes autorizados.
<MontoNoFacturable> — reembolsos, propina voluntaria. Puede ser negativo.
<NumeroFacturaInterna> — clave de dedup de negocio.
<CodigoVendedor>.
Bloque de pago del encabezado.
object
Una forma de pago. Type y Amount son nullable para distinguir “no vino” de un
valor: el validador exige ambos y la API nunca rellena uno por su cuenta.
object
Una línea de <DetallesItems>.
object
object
Desglose de impuestos adicionales por código de la Tabla I (001–039). Todos los
montos los trae el cliente ya calculados. iscEspecifico (monto fijo por
volumen: alcoholes 006-018, cigarrillos 019-022) integra la base imponible
del ITBIS de esa línea; iscAdvalorem y otros (Propina, CDT, ISC
de servicios, Primera Placa…) van “por encima”, sin tocar la base.
object
Campos opcionales del <Item> — passthrough. La derivación del
ISC desde alcoholDegrees/referenceQuantity es un slice posterior;
hoy el cliente trae el monto final del ISC en additionalTaxes (el ISC
específico ahí sí integra la base del ITBIS — ver EcfAdditionalTaxPayload).
object
object
<Mineria> — datos de liquidación minera (solo tipos 32/33/34/46).
object
Un descuento o recargo global (Sección D).
object
Facturación en divisa (<OtraMoneda>). El cliente trae los montos ya convertidos.
object
object
Datos de embarque (<InformacionesAdicionales>). Passthrough.
object
Datos de exportación (solo tipo 46).
object
Datos de transporte (<Transporte>). Passthrough.
object
Subtotal informativo para la RI (Sección C). No afecta la base imponible.
object
Página de la RI (<Paginacion>).
object
Totales declarados por el cliente (chequeo de tolerancia; nunca bloquea).
object
Payload de emisión de un e-CF (POST /api/v1/ecf). Un solo objeto
discriminado por int IssueEcfCommand.Type; el servidor asigna la secuencia, arma el
bloque Emisor desde el perfil del tenant, calcula los totales, firma y persiste.
object
Código DGII del tipo de e-CF: 31, 32, 33, 34, 41, 43, 44, 45, 46, 47.
E-NCF de 13 caracteres. Solo con sequences.mode = external (y
obligatorio ahí); con managed se rechaza, NovaFE asigna el suyo.
<FechaVencimientoSecuencia> del e-NCF. Con
sequences.mode = external es obligatorio en los tipos que llevan
vencimiento (todos menos 32 y 34) y no aplica en esos dos; en
managed se rechaza.
Fecha de emisión (calendario dominicano). Default: hoy.
<TipoIngresos> — “01”…“06”. Obligatorio en 31/32/33/34/44/45/46.
true si los precios de las líneas ya traen el ITBIS incluido.
<IndicadorEnvioDiferido> — solo contribuyentes autorizados.
<MontoNoFacturable> — reembolsos, propina voluntaria. Puede ser negativo.
<NumeroFacturaInterna> — clave de dedup de negocio.
<CodigoVendedor>.
Bloque de pago del encabezado.
object
Una forma de pago. Type y Amount son nullable para distinguir “no vino” de un
valor: el validador exige ambos y la API nunca rellena uno por su cuenta.
object
Una línea de <DetallesItems>.
object
object
Desglose de impuestos adicionales por código de la Tabla I (001–039). Todos los
montos los trae el cliente ya calculados. iscEspecifico (monto fijo por
volumen: alcoholes 006-018, cigarrillos 019-022) integra la base imponible
del ITBIS de esa línea; iscAdvalorem y otros (Propina, CDT, ISC
de servicios, Primera Placa…) van “por encima”, sin tocar la base.
object
Campos opcionales del <Item> — passthrough. La derivación del
ISC desde alcoholDegrees/referenceQuantity es un slice posterior;
hoy el cliente trae el monto final del ISC en additionalTaxes (el ISC
específico ahí sí integra la base del ITBIS — ver EcfAdditionalTaxPayload).
object
object
<Mineria> — datos de liquidación minera (solo tipos 32/33/34/46).
object
Un descuento o recargo global (Sección D).
object
Facturación en divisa (<OtraMoneda>). El cliente trae los montos ya convertidos.
object
object
Datos de embarque (<InformacionesAdicionales>). Passthrough.
object
Datos de exportación (solo tipo 46).
object
Datos de transporte (<Transporte>). Passthrough.
object
Subtotal informativo para la RI (Sección C). No afecta la base imponible.
object
Página de la RI (<Paginacion>).
object
Totales declarados por el cliente (chequeo de tolerancia; nunca bloquea).
object
Responses
Sección titulada «Responses»OK
Resultado de POST /api/v1/ecf/validate. Siempre llega con 200 cuando
el cuerpo se pudo leer y el contribuyente puede validar: bool ValidateEcfResultDto.Valid dice si
el comprobante pasaría la validación de forma y la matriz estructural y fiscal por
tipo (Módulo 2 + 6) que corre POST /ecf. No asigna una secuencia real, no
firma y no persiste nada. Lo que impide validar (sin autenticar, perfil del emisor
sin configurar) sigue siendo un error HTTP.
object
true si el comprobante se podría emitir tal cual en cuanto a su contenido.
Resumen en una frase, listo para mostrar.
Todos los problemas encontrados, no solo el primero. Vacío si bool ValidateEcfResultDto.Valid.
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
Avisos que no impiden emitir (p. ej. aceptación condicional probable).
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
La vista previa de lo que se emitiría; null si el comprobante no es válido.
object
Placeholder (E{tipo}0000000000) — nunca un e-NCF real, no se asignó
ninguna secuencia para construir este documento.
Estimado (31-dic del año siguiente a DateOnly ValidateEcfPreviewDto.IssueDate) cuando el tipo
lo lleva; no viene de una secuencia real. null en los tipos que no lo
llevan (32, 34).
Los totales quedarían fuera de la tolerancia de cuadratura (RF-06.6) — la DGII probablemente aceptaría el comprobante de forma condicional si se emite así.
Resultado de POST /api/v1/ecf/validate. Siempre llega con 200 cuando
el cuerpo se pudo leer y el contribuyente puede validar: bool ValidateEcfResultDto.Valid dice si
el comprobante pasaría la validación de forma y la matriz estructural y fiscal por
tipo (Módulo 2 + 6) que corre POST /ecf. No asigna una secuencia real, no
firma y no persiste nada. Lo que impide validar (sin autenticar, perfil del emisor
sin configurar) sigue siendo un error HTTP.
object
true si el comprobante se podría emitir tal cual en cuanto a su contenido.
Resumen en una frase, listo para mostrar.
Todos los problemas encontrados, no solo el primero. Vacío si bool ValidateEcfResultDto.Valid.
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
Avisos que no impiden emitir (p. ej. aceptación condicional probable).
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
La vista previa de lo que se emitiría; null si el comprobante no es válido.
object
Placeholder (E{tipo}0000000000) — nunca un e-NCF real, no se asignó
ninguna secuencia para construir este documento.
Estimado (31-dic del año siguiente a DateOnly ValidateEcfPreviewDto.IssueDate) cuando el tipo
lo lleva; no viene de una secuencia real. null en los tipos que no lo
llevan (32, 34).
Los totales quedarían fuera de la tolerancia de cuadratura (RF-06.6) — la DGII probablemente aceptaría el comprobante de forma condicional si se emite así.
Examplegenerated
{ "valid": true, "message": "example", "errors": [ { "field": "example", "code": "example", "message": "example" } ], "warnings": [ { "field": "example", "code": "example", "message": "example" } ], "preview": { "type": 1, "typeName": "example", "sampleEncf": "example", "issueDate": "2026-04-15", "sequenceExpiresOnEstimate": "2026-04-15", "montoGravadoTotal": 1, "montoExento": 1, "totalItbis": 1, "montoImpuestoAdicional": 1, "montoTotal": 1, "expectConditionalAcceptance": true }}Resultado de POST /api/v1/ecf/validate. Siempre llega con 200 cuando
el cuerpo se pudo leer y el contribuyente puede validar: bool ValidateEcfResultDto.Valid dice si
el comprobante pasaría la validación de forma y la matriz estructural y fiscal por
tipo (Módulo 2 + 6) que corre POST /ecf. No asigna una secuencia real, no
firma y no persiste nada. Lo que impide validar (sin autenticar, perfil del emisor
sin configurar) sigue siendo un error HTTP.
object
true si el comprobante se podría emitir tal cual en cuanto a su contenido.
Resumen en una frase, listo para mostrar.
Todos los problemas encontrados, no solo el primero. Vacío si bool ValidateEcfResultDto.Valid.
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
Avisos que no impiden emitir (p. ej. aceptación condicional probable).
Un error o aviso de POST /api/v1/ecf/validate.
object
Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.
Código estable, apto para lógica del cliente.
Descripción lista para mostrar.
La vista previa de lo que se emitiría; null si el comprobante no es válido.
object
Placeholder (E{tipo}0000000000) — nunca un e-NCF real, no se asignó
ninguna secuencia para construir este documento.
Estimado (31-dic del año siguiente a DateOnly ValidateEcfPreviewDto.IssueDate) cuando el tipo
lo lleva; no viene de una secuencia real. null en los tipos que no lo
llevan (32, 34).
Los totales quedarían fuera de la tolerancia de cuadratura (RF-06.6) — la DGII probablemente aceptaría el comprobante de forma condicional si se emite así.
Examplegenerated
{ "valid": true, "message": "example", "errors": [ { "field": "example", "code": "example", "message": "example" } ], "warnings": [ { "field": "example", "code": "example", "message": "example" } ], "preview": { "type": 1, "typeName": "example", "sampleEncf": "example", "issueDate": "2026-04-15", "sequenceExpiresOnEstimate": "2026-04-15", "montoGravadoTotal": 1, "montoExento": 1, "totalItbis": 1, "montoImpuestoAdicional": 1, "montoTotal": 1, "expectConditionalAcceptance": true }}Bad Request
object
object
object
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "errors": { "additionalProperty": [ "example" ] }}object
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example", "errors": { "additionalProperty": [ "example" ] }}