Ir al contenido

EcfValida un comprobante sin emitirlo

Valida un comprobante sin emitirlo

Ver como Markdown
POST
/api/v1/ecf/validate
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.

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
type
required

Código DGII del tipo de e-CF: 31, 32, 33, 34, 41, 43, 44, 45, 46, 47.

integer | string format: int32
default: 31 /^-?(?:0|[1-9]\d*)$/
encf

E-NCF de 13 caracteres. Solo con sequences.mode = external (y obligatorio ahí); con managed se rechaza, NovaFE asigna el suyo.

null | string
sequenceExpiresOn

&lt;FechaVencimientoSecuencia&gt; 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.

null | string format: date
issueDate

Fecha de emisión (calendario dominicano). Default: hoy.

null | string format: date
incomeType

&lt;TipoIngresos&gt; — “01”…“06”. Obligatorio en 31/32/33/34/44/45/46.

null | string
pricesIncludeTax

true si los precios de las líneas ya traen el ITBIS incluido.

boolean
deferredDelivery

&lt;IndicadorEnvioDiferido&gt; — solo contribuyentes autorizados.

boolean
nonInvoiceableAmount

&lt;MontoNoFacturable&gt; — reembolsos, propina voluntaria. Puede ser negativo.

number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
internalNumber

&lt;NumeroFacturaInterna&gt; — clave de dedup de negocio.

null | string
sellerCode

&lt;CodigoVendedor&gt;.

null | string
additionalInfo
One of:
null
buyer
One of:
null
payment

Bloque de pago del encabezado.

object
condition
null | string
dueDate
null | string format: date
methods
Array<object> | null

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
type
required
null | string
amount
required
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
lines
required
Array<object>

Una línea de &lt;DetallesItems&gt;.

object
name
required
null | string
kind
null | string
quantity
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
unitPrice
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbisRate
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
unitOfMeasure
null | string
description
null | string
discount
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
surcharge
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
priceIncludesTax
null | boolean
declaredAmount
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
codes
Array<object> | null
object
type
required
string
value
required
string
retention
One of:
null
additionalTaxes
Array<object> | null

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
code
required
string
rate
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
iscEspecifico
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
iscAdvalorem
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
otros
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
foreignCurrency
One of:
null
details
One of:
null
reference
One of:
null
globalAdjustments
Array<object> | null

Un descuento o recargo global (Sección D).

object
line
required
integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
kind
string
default: discount
affectsItbisRate
integer | string format: int32
default: 1 /^-?(?:0|[1-9]\d*)$/
amount
number | string format: double
0 /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
norm1007
boolean
description
null | string
percentage
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
foreignCurrency
One of:
null
shipping
One of:
null
transport
One of:
null
subtotals
Array<object> | null

Subtotal informativo para la RI (Sección C). No afecta la base imponible.

object
number
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
description
null | string
order
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
montoGravadoTotal
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI1
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI2
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI3
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
totalItbis
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis1
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis2
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis3
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoImpuestoAdicional
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoExento
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
amount
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
lines
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
pagination
Array<object> | null

Página de la RI (&lt;Paginacion&gt;).

object
number
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
lineFrom
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
lineTo
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
montoGravadoTotal
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI1
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI2
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoGravadoI3
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoExento
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
totalItbis
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis1
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis2
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
itbis3
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
montoImpuestoAdicional
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
iscEspecifico
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
otrosImpuestos
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
amount
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
nonInvoiceableAmount
null | number | string format: double
/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/
declaredTotals
One of:
null

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
valid
required

true si el comprobante se podría emitir tal cual en cuanto a su contenido.

boolean
message
required

Resumen en una frase, listo para mostrar.

string
errors
required

Todos los problemas encontrados, no solo el primero. Vacío si bool ValidateEcfResultDto.Valid.

Array<object>

Un error o aviso de POST /api/v1/ecf/validate.

object
field
required

Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.

null | string
code
required

Código estable, apto para lógica del cliente.

string
message
required

Descripción lista para mostrar.

string
warnings
required

Avisos que no impiden emitir (p. ej. aceptación condicional probable).

Array<object>

Un error o aviso de POST /api/v1/ecf/validate.

object
field
required

Campo del payload al que se refiere (p. ej. Lines[0].Quantity); null si es de todo el comprobante.

null | string
code
required

Código estable, apto para lógica del cliente.

string
message
required

Descripción lista para mostrar.

string
preview
required
One of:
null

Bad Request

object
type
null | string
title
null | string
status
null | integer | string format: int32
/^-?(?:0|[1-9]\d*)$/
detail
null | string
instance
null | string
errors
object
key
additional properties
Array<string>