Esta API permite que cualquier sistema (ERP, POS, facturador propio) emita comprobantes fiscales electrónicos ante la DGII con una llamada HTTP. Nosotros nos encargamos de la firma digital XAdES con tu certificado .p12, la autenticación con la DGII, el envío, el seguimiento y los acuses.
1. Cómo funciona la integración
Tu sistema nunca habla directamente con la DGII ni maneja el certificado. Solo envía el documento en JSON (o XML sin firmar) a nuestro endpoint de emisión y consulta el estado con el trackId.
Tu sistema (ERP/POS)
│ POST /api/v1/ecf/emit → archivo/llamada para ENVIAR la factura
▼
Bridge DGII
│ 1. valida tu API key
│ 2. arma el XML del e-CF
│ 3. lo firma (XAdES) con tu certificado .p12 cifrado
│ 4. autentica contra la DGII (semilla → token)
│ 5. envía el e-CF y guarda el trackId
▼
DGII (TesteCF / CerteCF / Producción)
│
▼
Tu sistema
GET /api/v1/ecf/track/:trackId → llamada para CONSULTAR EL ESTATUS
(o recibes un webhook cuando cambia el estado)
Necesito…
Endpoint
Probar que mi conexión y certificado funcionan
GET /api/v1/status
Un ejemplo listo para enviar
GET /api/v1/ecf/sample
ENVIAR una factura
POST /api/v1/ecf/emit
CONSULTAR el estatus en la DGII
GET /api/v1/ecf/track/:trackId
Ver un documento que ya emití
GET /api/v1/ecf/:id
Verificar validez de un e-CF
POST /api/v1/ecf/inquiry
Anular secuencias no usadas
POST /api/v1/ecf/void
2. Ambientes y URL base
La URL base de la API es siempre la de esta plataforma. El ambiente de la DGII se define en el panel (tarjeta “Información de la empresa”), no en la petición.
Base URL (producción de la plataforma): https://ecf.grstech.com.do
Base URL (preview): https://ecf.grstech.com.do
Todas las rutas van bajo /api/v1
Ambiente
Valor
Host DGII
Pruebas (TesteCF)
dev
https://ecf.dgii.gov.do/testecf
Certificación (CerteCF)
cert
https://ecf.dgii.gov.do/certecf
Producción
prod
https://ecf.dgii.gov.do/ecf
3. Autenticación (API key)
Genera la key en el panel → API Keys. Se muestra una sola vez, empieza con bdgii_ y queda ligada a tu organización, su RNC y su certificado. Envíala en cada petición en el header x-api-key o como Authorization: Bearer.
El body de /api/v1/ecf/emit tiene campos de control (para nuestro registro) y el documento en sí.
Campo
Tipo
Obligatorio
Descripción
tipoEcf
string(2)
Sí
Tipo de e-CF: 31, 32, 33, 34, 41, 43, 44, 45, 46, 47.
encf
string
Sí
Secuencia e-NCF, ej. E310000000001. Debe estar dentro de un rango autorizado.
rncEmisor
string(9-11)
Sí
RNC del emisor; debe coincidir con el de tu organización y certificado.
rncComprador
string(9-11)
No
RNC/cédula del comprador. Obligatorio para tipos con crédito fiscal (31).
montoTotal
number
No
Total del documento; se usa para reportes en el panel.
summary
boolean
No
true = envío por resumen (RFCE, consumo < RD$250,000).
document
object
Sí (o xml)
Documento e-CF en JSON con la estructura ECF → Encabezado, DetallesItems, Paginacion.
xml
string
Sí (o document)
XML del e-CF SIN firmar, si prefieres generarlo tú. Nosotros lo firmamos.
Dentro de document.ECF: fechas en formato DD-MM-AAAA, FechaHoraFirma como DD-MM-AAAA HH:mm:ss, montos numéricos con 2 decimales, e ITBIS 18% en TotalITBIS. Los totales de Paginacion deben cuadrar con los de Totales, de lo contrario la DGII rechaza el documento.
7. Estados y ciclo de vida
sending — firmado y enviándose a la DGII.
sent — recibido por la DGII con trackId asignado; falta el resultado final.
accepted — aceptado (respuesta sin trackId o tracking confirmado).
error — fallo de firma, validación o comunicación; revisa error_message.
El estado definitivo lo da la DGII en el tracking: Aceptado, Aceptado Condicional, Rechazado o En Proceso. Un documento rechazado requiere corregir y emitir una secuencia nueva.
8. Errores y códigos HTTP
Código
Significado
Qué hacer
200 / 201
Operación correcta (201 al emitir).
Guarda id y track_id.
400
Payload inválido o faltan xml/document.
Revisa el campo details del error.
401
API key ausente, inválida o desactivada.
Verifica el header x-api-key.
404
Documento no encontrado para tu organización.
Confirma el id.
500
Error interno al leer datos.
Reintenta; si persiste, contáctanos.
502
Error de firma o de comunicación con la DGII.
Revisa el certificado y el estado del servicio DGII; reintenta.
import os, requests
BASE = "https://ecf.grstech.com.do"
H = {"x-api-key": os.environ["BRIDGE_API_KEY"]}
doc = requests.post(f"{BASE}/api/v1/ecf/emit", json=factura, headers=H).json()["data"]
estado = requests.get(f"{BASE}/api/v1/ecf/track/{doc['track_id']}", headers=H).json()["data"]
print(estado["estado"])
10. Webhooks
Alternativa al polling: configúralos en el panel → Webhooks. Cuando cambia el estado de un documento enviamos un POST JSON a tu URL con la firma HMAC-SHA256 del cuerpo en el header x-bridge-signature. Verifícala con el secreto mostrado al crear el webhook y responde 2xx.
Los e-CF que te envían tus proveedores y las aprobaciones comerciales entran por las URLs registradas en la DGII y quedan guardados en tu buzón. Tu sistema (Trillonic) los lee con estos dos endpoints, usando la misma x-api-key.
Importante: el buzón está separado por ambiente. Si no ves documentos, agrega ?environment=prod (o dev / cert); sin ese parámetro se devuelve solo el ambiente activo de la empresa. Para empresas asociadas envía el header x-org-id.
GET/api/v1/inbound
Lista los documentos recibidos (e-CF de proveedores y aprobaciones comerciales).
¿Cuándo se usa?Cada pocos minutos desde Trillonic para sincronizar el buzón de entrada.
Filtros disponibles en la lista: environment, status, rncEmisor, encf, since (fecha ISO) y limit (1–200).
// Sincronizar el buzón en Trillonic (Node.js)
const BASE = "https://ecf.grstech.com.do";
const H = { "x-api-key": process.env.BRIDGE_API_KEY };
const desde = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const r = await fetch(
`${BASE}/api/v1/inbound?environment=prod&since=${desde}&limit=200`,
{ headers: H },
);
const { data } = await r.json();
for (const doc of data) {
const det = await fetch(`${BASE}/api/v1/inbound/${doc.id}`, { headers: H });
const { data: completo } = await det.json();
// completo.xml trae el e-CF recibido; regístralo como compra en Trillonic.
}
// Bajar solo el archivo XML (emitido o recibido), por id o por e-NCF:
const xmlRecibido = await (await fetch(
`${BASE}/api/v1/inbound/E310000016244/xml?environment=prod`, { headers: H },
)).text();
const xmlEmitido = await (await fetch(
`${BASE}/api/v1/ecf/E310000000005/xml?environment=prod`, { headers: H },
)).text();
12. URLs a registrar en la DGII
Para recibir e-CF de tus proveedores y aprobaciones comerciales, registra estas URLs en el portal de la DGII:
Si manejas varios RNC, añade ?rnc=RNC a cada URL. Los documentos recibidos aparecen en Documentos → Recibidos y en GET /api/v1/inbound.
13. Preguntas frecuentes
¿Cuál es el “archivo” para enviar facturas?
No se sube archivo: se hace un POST JSON a /api/v1/ecf/emit. Si tu sistema ya genera XML, mándalo sin firmar en el campo xml y nosotros lo firmamos.
¿Y para consultar el estatus?
GET /api/v1/ecf/track/:trackId con el trackId que devuelve la emisión. También puedes usar GET /api/v1/ecf/:id para ver el registro interno.
¿Debo firmar el XML en mi sistema?
No. La firma XAdES se hace aquí con tu certificado .p12 cifrado; tu sistema nunca maneja la llave privada.
¿Quién controla la secuencia e-NCF?
Tu sistema. Debes enviar un eNCF único dentro de un rango autorizado por la DGII; no reutilices secuencias.
¿Cómo paso de pruebas a producción?
Cambia el ambiente de la organización a Producción en el panel y vuelve a probar la conexión. La API key y los endpoints siguen siendo los mismos.
¿Hay límite de tamaño?
Los e-CF de consumo menores a RD$250,000 pueden enviarse por resumen (summary: true, RFCE).
14. Multi-cliente (empresas asociadas)
Si eres integrador (por ejemplo un ERP con muchos clientes), usas una sola API key (la de tu empresa principal) y creas una empresa asociada por cada cliente final. Cada empresa asociada tiene su propio RNC, certificado .p12, secuencias, documentos y ambiente DGII. Tus clientes no necesitan API key propia.
Tu sistema (integrador) ── x-api-key: bdgii_xxx (tu key)
│
├─ POST /api/v1/orgs → crea la empresa asociada (cliente)
├─ POST /api/v1/orgs/:orgId/certificate → sube su .p12 (cifrado AES-256-GCM)
│
└─ POST /api/v1/ecf/emit + x-org-id: :orgId → emite a nombre de ese cliente
Guarda el org.id en tu base de datos junto al cliente. Requiere que tu key tenga el scope orgs:manage.
2. Subir el certificado del cliente
curl -X POST "$BASE/api/v1/orgs/ORG_ID/certificate" \
-H "x-api-key: $KEY" -H "content-type: application/json" \
-d '{
"alias": "Certificado 2026",
"p12Base64": "<contenido del .p12 en base64>",
"password": "clave-del-certificado"
}'
El .p12 se cifra con AES-256-GCM y se archiva en almacenamiento privado. Desde tu sistema puedes ofrecer al cliente un formulario de carga y reenviarnos el archivo en base64.
El header x-org-id también funciona en /api/v1/ecf/track/:trackId, /api/v1/ecf/inquiry, /api/v1/ecf/void, /api/v1/ecf/:id, /api/v1/ecf/sample y /api/v1/status. En los GET puedes usar además ?orgId=ORG_ID.
Seguridad
x-org-id solo se acepta si esa empresa fue creada bajo tu organización; cualquier otro id devuelve 403.
Sin el header, todo se emite con tu propia organización y certificado.
Cada cliente puede tener su propio ambiente (dev/cert/prod) sin afectar a los demás.