import { Aside } from "@astrojs/starlight/components";

`POST /api/v1/ecf/validate` recibe el mismo cuerpo que
[`POST /ecf`](/emision/endpoints-y-semantica/) y corre exactamente la misma
validación de forma y de reglas fiscales, matriz de obligatoriedad
incluida, y además comprueba el XML resultante contra el esquema (XSD) oficial
de la DGII. La diferencia es que ahí se detiene: no asigna un e-NCF real, no
firma, no persiste ni encola nada hacia la DGII.

<Aside type="tip" title="No necesitas certificado ni secuencias configuradas">
  Para validar un payload solo hace falta tu perfil fiscal (el que arma el
  bloque `<Emisor>`). No necesitas tener un certificado cargado ni un rango
  de secuencias autorizado todavía, así que puedes usarlo desde el primer
  día de tu integración.
</Aside>

## Respuesta

La respuesta es `200` siempre que NovaFE pueda evaluar el comprobante, y el
campo `valid` indica si pasa la validación. Un comprobante inválido no es
un error HTTP: el cuerpo trae **todos** sus problemas a la vez, no solo el
primero.

Uno válido incluye una vista previa de lo que NovaFE emitiría:

```json
{
  "valid": true,
  "message": "El comprobante es válido.",
  "errors": [],
  "warnings": [],
  "preview": {
    "type": 31,
    "typeName": "Factura de Crédito Fiscal Electrónica",
    "sampleEncf": "E310000000000",
    "issueDate": "10-01-2026",
    "sequenceExpiresOnEstimate": "31-12-2027",
    "montoGravadoTotal": 2000.0,
    "montoExento": 0,
    "totalItbis": 360.0,
    "montoImpuestoAdicional": 0,
    "montoTotal": 2360.0,
    "expectConditionalAcceptance": false
  }
}
```

Uno inválido devuelve `valid: false`, la lista en `errors` y `preview: null`:

```json
{
  "valid": false,
  "message": "El comprobante tiene 2 errores.",
  "errors": [
    { "field": "Lines", "code": "NotEmptyValidator", "message": "..." },
    { "field": null, "code": "Ecf.SomeRule", "message": "..." }
  ],
  "warnings": [],
  "preview": null
}
```

- `errors[].field` indica el campo del cuerpo cuando el problema es de forma,
  y es `null` cuando afecta a todo el comprobante. `code` es estable, para que
  tu código decida con él; `message` está listo para mostrar.
- Un valor que cumple la forma pero no el esquema de la DGII (por ejemplo, un
  texto más largo de lo que admite el campo) sale con el código `Ecf.XsdInvalid`,
  y el mensaje nombra el elemento XML afectado. Cada violación es un error
  aparte. `POST /ecf` hace esta misma comprobación antes de asignar el e-NCF:
  si falla, responde `400` y no consume ningún número.
- `warnings` no impiden emitir. Por ejemplo, `ConditionalAcceptanceExpected`
  avisa que los totales no cuadran dentro de la tolerancia de la DGII y que
  es probable que la acepte de forma condicional. También avisan los bloques
  informativos que no cuadran con las líneas: otra moneda
  (`ForeignCurrencyConversionMismatch`), subtotales (`SubtotalGrossMismatch`,
  `SubtotalAmountMismatch`) y paginación (`PageBucketMismatch`,
  `PageAmountMismatch`, `PageSumMismatch`). El comprobante sigue siendo válido
  y no se rechaza.

Siguen siendo errores HTTP los casos donde no hay nada que evaluar: un
cuerpo que no es JSON válido (`400`), una petición sin autenticar y un
contribuyente sin perfil fiscal configurado.

<Aside type="caution" title="sampleEncf nunca es un e-NCF real">
  Es un valor de relleno (`E` más el tipo más ceros) armado solo para poder
  construir el documento de prueba. Validar un payload nunca toca tu rango de
  secuencias real. `sequenceExpiresOnEstimate` es solo una estimación (31 de
  diciembre del año siguiente a `issueDate`): el vencimiento real lo indicas tú
  al registrar el rango. Ambos campos están ausentes en los tipos 32 y 34, que
  no tienen fecha de vencimiento de secuencia.
</Aside>