e‑CFe-cf.com.do

API de facturación electrónica

URL base https://e-cf.com.do/api/public/v1. Todas las respuestas son JSON.

Autenticación

Genere una API Key en su portal (Integración). Envíela en cada petición:

Authorization: Bearer ecf_live_xxxxxxxxxxxxxxxx
# o bien
X-API-Key: ecf_live_xxxxxxxxxxxxxxxx

Las llaves ecf_test_ trabajan contra pre-certificación o certificación; ecf_live_ contra producción.

Pruebas de integración sin DGII

Genere una clave ecf_sandbox_ en la pestaña Pruebas de integración. Use la URL https://e-cf.com.do/api/public/sandbox/v1, no la URL fiscal. Las claves de pruebas no funcionan en la API fiscal y las fiscales no funcionan aquí.

curl -X POST https://e-cf.com.do/api/public/sandbox/v1/ecf \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: PRUEBA-001" \
  -d '{"tipo":32,"items":[{"nombre":"Prueba","cantidad":1,"precioUnitario":1000,"itbis":18}]}'

Datos válidos: HTTP 201 y ACEPTADO. Datos inválidos: HTTP 422 y RECHAZADO con validacion.errores por campo. Un reintento con la misma clave devuelve la prueba original (HTTP 200); si cambia el JSON, HTTP 409.

GET /ecf lista las pruebas; GET /ecf/{id} recupera el resultado; GET /ecf/{id}/xml descarga una vista sin firma, con e-NCF cero como marcador. El identificador es SIM-…, no un e-NCF fiscal.

Siempre devuelve simulado: true, enviadoDGII: false y validezFiscal: false. No usa certificados, secuencias, QR, webhooks reales ni conexión DGII. Valida JSON, campos requeridos, fechas, descuentos y cálculos locales; no valida XSD ni garantiza aceptación de la DGII. Certificación y producción continúan en la API fiscal.

Emitir e-CF

POST /ecf — Nosotros asignamos el e-NCF, generamos el XML oficial, lo firmamos y lo enviamos a la DGII. Use Idempotency-Key para que un reintento no cree una factura duplicada.

curl -X POST https://e-cf.com.do/api/public/v1/ecf \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: FAC-1001" \
  -d '{
  "tipo": 31,
  "fechaEmision": "2026-10-22",
  "tipoPago": 1,
  "comprador": { "rnc": "101000000", "razonSocial": "CLIENTE SRL" },
  "items": [
    { "nombre": "Servicio de consultoría", "cantidad": 10,
      "precioUnitario": 1500.50, "itbis": 18, "esServicio": true },
    { "nombre": "Libro", "cantidad": 2, "precioUnitario": 850, "itbis": 0 }
  ]
}'
CampoDescripción
tipo31, 32, 33, 34, 41, 43, 44, 45, 46, 47
tipoPago1 contado · 2 crédito (requiere fechaLimitePago) · 3 gratuito
comprador.rncObligatorio en 31, 41 y 45
referenciaNotas 33/34: { ncfModificado, fechaNcfModificado, codigoModificacion }
items[].precioUnitarioHasta 4 decimales; montos se redondean a 2
items[].itbis18, 16 o 0 (exento)

Las facturas de consumo (32) menores a RD$250,000 se envían como resumen (RFCE) y reciben respuesta inmediata. Las demás quedan EN_PROCESO con un TrackId.

HTTP/1.1 201 Created
{
  "id": "2e1b...",
  "encf": "E310000000001",
  "status": "EN_PROCESO",
  "trackId": "90442598-e9e4-...",
  "montoTotal": 19405.9,
  "codigoSeguridad": "0lyqgX",
  "fechaFirma": "22-10-2026 15:13:54",
  "qrUrl": "https://ecf.dgii.gov.do/ecf/ConsultaTimbre?RncEmisor=...",
  "links": { "self": ".../ecf/2e1b...", "xml": ".../ecf/2e1b.../xml" }
}

Consultar

  • GET /ecf — lista (?status=ACEPTADO&limit=50)
  • GET /ecf/{id | eNCF} — estado; si está en proceso consultamos la DGII en ese momento
  • GET /ecf/{id}/xml — XML firmado
  • POST /ecf/{id} — reintenta el envío si quedó en ERROR_ENVIO
  • GET /recibidos — e-CF recibidos de sus suplidores

Estados

FIRMADO → EN_PROCESO → ACEPTADO | ACEPTADO_CONDICIONAL | RECHAZADO. Si no pudimos comunicarnos con la DGII: ERROR_ENVIO (el e-NCF se conserva, reintente).

Si un RFCE es rechazado con secuenciaUtilizada: true, ese e-NCF ya no puede usarse: emita uno nuevo.

Webhook

Configure su URL en el portal. Cuando el estado sea final enviamos:

POST https://su-erp.com/webhooks/ecf
X-ECF-Signature: hex(HMAC-SHA256(secreto, cuerpo))
{ "event": "ecf.status", "data": { ...mismo formato que GET /ecf/{id} } }

Anulación de secuencias

POST https://e-cf.com.do/api/public/v1/anulaciones
{ "rangos": [ { "tipo": 31, "desde": "E310000000500", "hasta": "E310000000510" } ] }

Aprobación comercial

Apruebe (1) o rechace (2) un e-CF recibido de un suplidor:

POST https://e-cf.com.do/api/public/v1/aprobaciones
{ "rncEmisor": "131880681", "encf": "E310000000099",
  "fechaEmision": "2026-10-22", "montoTotal": 1180, "estado": 1 }

URLs de receptor

Regístrelas en la Oficina Virtual de la DGII. Reemplace {RNC} por el suyo:

GET  https://e-cf.com.do/api/public/fe/{RNC}/semilla
POST https://e-cf.com.do/api/public/fe/{RNC}/validacioncertificado
POST https://e-cf.com.do/api/public/fe/{RNC}/recepcion            -> responde ARECF firmado
POST https://e-cf.com.do/api/public/fe/{RNC}/aprobacioncomercial

Errores

401API Key ausente, inválida o revocada
404Comprobante no encontrado
409Sin certificado o sin secuencias disponibles
422Datos inválidos — revise detalles
502La DGII respondió con error — revise detalle