¿Buscas la versión anterior (v2.0.1)? Los paquetes .NET (
SSDDO.ECF_DGII.Models/SSDDO.ECF_DGII.SDK) están disponibles en la rama2.0.1-legacy.
SDKs oficiales para integrar la facturación electrónica (e-CF) en República Dominicana a través de ECF SSD.
| Plataforma | Paquete | Instalación | Docs |
|---|---|---|---|
| .NET | dotnet add package SSDDO.ECF_DGII.SDK |
README | |
| TypeScript | npm install @ssddo/ecf-sdk |
README | |
| React | npm install @ssddo/ecf-react |
README | |
| Python | pip install ecf-dgii |
README | |
| PHP | composer require ecfx/ecf-dgii-php |
README | |
| Java | implementation 'do.com.ssd.ecfx:ecf-dgii-sdk-java:1.0.0' |
README | |
| Kotlin | implementation("do.com.ssd.ecfx:ecf-dgii-sdk-kotlin:1.0.0") |
README | |
| iOS/Swift | Swift Package Manager | Ver ios/README.md | README |
| C++ | vcpkg / Conan | Ver C++/README.md | README |
ECF SSD es una plataforma que simplifica la emisión de comprobantes fiscales electrónicos (e-CF) en República Dominicana. En vez de que cada empresa implemente todo el proceso de comunicación con la DGII (firmado XML, autenticación por semilla, manejo de certificados, reintentos, almacenamiento, etc.), ECF SSD lo hace por ti.
Tú solo envías el comprobante en JSON a través de estos SDKs, y el servicio se encarga de:
- Firmar el comprobante electrónicamente (XML signing con tu certificado digital)
- Autenticar con la DGII (semilla → token)
- Enviar el e-CF a la DGII
- Validar emisor-receptor
- Almacenar los comprobantes de forma segura
- Reintentar automáticamente en caso de fallos
- Gestionar tus certificados digitales
Visita https://ecf.ssd.com.do y crea tu cuenta.
Genera tu API Key (JWT) desde el panel de ECF SSD. Este token es el que usarás para autenticarte con los SDKs durante el desarrollo y la certificación.
Contacta al equipo de ECF SSD para iniciar el proceso de integración y certificación de tu sistema (no de las empresas de tus clientes — la certificación es para tu plataforma). El equipo te guiará a través del proceso usando el ambiente de certificación (Cert).
Una vez que tu sistema esté integrado y certificado, podrás usar el ambiente de producción (Prod) para emitir comprobantes fiscales electrónicos reales para las empresas de tus clientes.
¿Vienes de otro proveedor? ECF SSD soporta migración desde otros proveedores de facturación electrónica. Contacta al equipo para coordinar la transición.
Instala el SDK de tu lenguaje preferido y comienza a enviar comprobantes:
// .NET
var client = new EcfClient(new EcfClientOptions
{
ApiKey = "tu-jwt-token",
Environment = EcfEnvironment.Prod
});
var ecf = new ECF
{
Encabezado = new Encabezado
{
IdDoc = new IdDoc
{
TipoeCF = TipoeCFType.FacturaDeCreditoFiscalElectronica,
Encf = "E310000000001"
},
Emisor = new Emisor
{
RncEmisor = "123456789",
RazonSocialEmisor = "Mi Empresa SRL",
DireccionEmisor = "Calle Principal #1, Santo Domingo",
FechaEmision = DateTimeOffset.Now
},
Totales = new Totales { /* montos, ITBIS, etc. */ }
},
DetallesItems = new List<Item>
{
new Item
{
NombreItem = "Servicio de consultoría",
IndicadorFacturacion = IndicadorFacturacionType.NoFacturable_18Percent,
CantidadItem = 1,
PrecioUnitarioItem = 10000.00,
MontoItem = 10000.00
}
}
};
// Envía y espera el resultado — una sola llamada
EcfResponse resultado = await client.SendEcfAsync(ecf);
Console.WriteLine($"Estado: {resultado.Progress}");
Console.WriteLine($"Código seguridad: {resultado.CodSec}");// TypeScript
import { EcfClient } from 'ecf-dgii-client';
const client = new EcfClient({
apiKey: 'tu-jwt-token',
environment: 'prod',
});
const resultado = await client.sendEcf({
encabezado: {
idDoc: {
tipoeCF: 'FacturaDeCreditoFiscalElectronica',
encf: 'E310000000001',
},
emisor: {
rncEmisor: '123456789',
razonSocialEmisor: 'Mi Empresa SRL',
},
totales: { /* ... */ },
},
detallesItems: [
{
nombreItem: 'Servicio de consultoría',
cantidadItem: 1,
precioUnitarioItem: 10000.00,
montoItem: 10000.00,
}
],
});# Python
from ecf_dgii_client import EcfClient
client = EcfClient(
api_key="tu-jwt-token",
environment="prod",
)
resultado = client.send_ecf({
"encabezado": {
"idDoc": {
"tipoeCF": "FacturaDeCreditoFiscalElectronica",
"encf": "E310000000001",
},
"emisor": {
"rncEmisor": "123456789",
"razonSocialEmisor": "Mi Empresa SRL",
},
},
"detallesItems": [
{
"nombreItem": "Servicio de consultoría",
"cantidadItem": 1,
"precioUnitarioItem": 10000.00,
"montoItem": 10000.00,
}
],
})| Ambiente | URL | Uso |
|---|---|---|
| Test | https://api.test.ecfx.ssd.com.do |
Desarrollo y pruebas internas |
| Cert | https://api.cert.ecfx.ssd.com.do |
Proceso de certificación con la DGII |
| Prod | https://api.prod.ecfx.ssd.com.do |
Producción |
Todos los SDKs utilizan JWT Bearer Token para autenticarse. Puedes configurar el token de dos formas:
- Directamente en el código: pasando el API Key al crear el cliente
- Variable de entorno:
ECF_API_KEY(todos los SDKs la leen automáticamente)
| Tipo | Código | Ruta API |
|---|---|---|
| Factura de Crédito Fiscal Electrónica | E31 | /ecf/31 |
| Factura de Consumo Electrónica | E32 | /ecf/32 |
| Nota de Débito Electrónica | E33 | /ecf/33 |
| Nota de Crédito Electrónica | E34 | /ecf/34 |
| Compras Electrónico | E41 | /ecf/41 |
| Gastos Menores Electrónico | E43 | /ecf/43 |
| Regímenes Especiales Electrónico | E44 | /ecf/44 |
| Gubernamental Electrónico | E45 | /ecf/45 |
| Comprobante de Exportaciones Electrónico | E46 | /ecf/46 |
| Comprobante para Pagos al Exterior Electrónico | E47 | /ecf/47 |
Todos los SDKs incluyen un método de alto nivel (SendEcfAsync, sendEcf, send_ecf) que encapsula toda la complejidad:
sequenceDiagram
participant App as Tu Sistema
participant ECF as ECF SSD
participant DGII as DGII
App->>ECF: sendEcf(ecf)
ECF->>ECF: Firma XML
ECF->>DGII: Autenticación (semilla)
ECF->>DGII: Envío e-CF
DGII-->>ECF: { trackId }
loop Polling con backoff exponencial
ECF->>DGII: Consulta estado
DGII-->>ECF: { estado }
end
ECF-->>App: EcfResponse { codSec, impresionUrl, ... }
- Enrutamiento automático: Determina el endpoint correcto (
/ecf/31,/ecf/32, etc.) basándose en eltipoeCFdel comprobante - Envío: POST al endpoint correspondiente
- Polling con backoff exponencial: Consulta periódicamente el estado hasta que la DGII responda (
FinishedoError) - Resultado: Retorna el
EcfResponsecon el estado final, código de seguridad, URL de impresión, etc.
Al completarse el envío, recibes un EcfResponse con los datos necesarios para cumplir con los requisitos de impresión de la DGII:
| Campo | Descripción |
|---|---|
ImpresionUrl |
URL para generar el código QR requerido por la DGII en el comprobante impreso |
CodSec |
Código de seguridad — debe aparecer en el comprobante impreso |
FechaFirma |
Fecha y hora de la firma digital del comprobante |
Estatus |
Estado DGII: Aceptado, AceptadoCondicional, Rechazado |
Progress |
Estado del procesamiento: Queued, Sending, Polling, Finished, Error |
Encf |
Número de comprobante fiscal electrónico (eNCF) |
Mensaje |
Mensaje de respuesta de la DGII |
Errors |
Detalle de errores (si los hay) |
MontoTotal |
Monto total del comprobante |
SecuenciaUtilizada |
Indica si la secuencia fue utilizada |
La DGII requiere que todo comprobante impreso incluya un código QR. El campo ImpresionUrl contiene la URL que debe codificarse como QR. Adicionalmente, el CodSec (código de seguridad) y la FechaFirma deben aparecer impresos en el comprobante.
// .NET
EcfResponse resultado = await client.SendEcfAsync(ecf);
string urlQr = resultado.ImpresionUrl; // codificar como QR
string codigoSeguridad = resultado.CodSec; // imprimir en el comprobante
DateTimeOffset fechaFirma = resultado.FechaFirma; // fecha de firma digital// TypeScript
const resultado = await client.sendEcf(ecf);
const urlQr = resultado.impresionUrl; // codificar como QR
const codigoSeguridad = resultado.codSec; // imprimir en el comprobante
const fechaFirma = resultado.fechaFirma; // fecha de firma digital# Python
resultado = client.send_ecf(ecf)
url_qr = resultado.impresion_url # codificar como QR
codigo_seguridad = resultado.cod_sec # imprimir en el comprobante
fecha_firma = resultado.fecha_firma # fecha de firma digitalsequenceDiagram
participant C as Cliente (Browser/App)
participant BE as Backend
participant ECF as ECF API
C->>BE: POST /invoice (datos de factura)
Note over BE: Valida, guarda y convierte a formato ECF
BE->>ECF: POST /ecf/{tipo} (enviar ECF)
ECF-->>BE: { messageId }
BE-->>C: { messageId }
Note over C: No espera — puede continuar
alt Token en cache
C->>C: Usar token existente
else Sin token o expirado
C->>BE: GET /ecf-token
BE->>ECF: POST /apikey (solo lectura, scoped a RNC)
ECF-->>BE: { apiKey }
BE-->>C: { apiKey }
C->>C: Almacenar token en cache
end
loop Polling hasta completar
C->>ECF: GET /ecf/{rnc}/{encf} (token solo lectura)
ECF-->>C: { progress, codSec, ... }
end
- El cliente (browser/app) envía los datos de la factura al backend (
POST /invoice,/order,/sale) - El backend valida, guarda y convierte la factura interna al formato ECF
- El backend envía el ECF a la API de ECF SSD (
POST /ecf/{tipo}) y recibe unmessageId - El backend retorna el
messageIdal cliente — el cliente no espera, puede continuar - Cuando el cliente necesita consultar el estado del ECF, usa
EcfFrontendClientque internamente:- Verifica si hay un token de solo lectura en cache
- Si no existe o expiró: llama a
getToken()(que el consumidor provee — típicamente unfetch('/ecf-token')a su backend), luego llama acacheToken(token)para almacenarlo - Si la API retorna 401: automáticamente llama a
getToken()de nuevo, actualiza el cache, y reintenta
- El cliente hace polling directamente contra la API de ECF SSD (
GET /ecf/{rnc}/{encf}) hasta queprogressseaFinished
- Descarga el backend: Las consultas de estado (polling) las hace el cliente directamente contra ECF SSD.
- Seguridad: El token del cliente es de solo lectura y está limitado al tenant/RNC. No puede enviar comprobantes ni modificar datos.
- Tiempo real: El cliente puede hacer polling del estado sin depender del backend.
- Token automático:
EcfFrontendClientmaneja el ciclo de vida del token — cache, refresh en 401, y reintento.
import { EcfClient } from '@ssddo/ecf-sdk';
const ecfClient = new EcfClient({
apiKey: process.env.ECF_BACKEND_TOKEN,
environment: 'prod',
});
// Tu endpoint de facturación — lógica de negocio + envío a ECF SSD
app.post('/api/v1/invoices', async (req, res) => {
const invoice = await validateAndSave(req.body);
const ecf = convertToEcf(invoice);
const { data } = await ecfClient.raw.POST('/ecf/31', { body: ecf });
await updateInvoice(invoice.id, { messageId: data.messageId });
res.json({ id: invoice.id, messageId: data.messageId, rnc: ecf.encabezado.emisor.rncEmisor, encf: ecf.encabezado.idDoc.encf });
});
// Generar token de solo lectura para el cliente
app.get('/api/v1/ecf-token', async (req, res) => {
const { data } = await ecfClient.createApiKey({ rnc: tenant.rnc });
res.json({ apiKey: data.token });
});import { createEcfFrontendReactClient } from '@ssddo/ecf-react';
// 1. Crear cliente de solo lectura (getToken se llama automáticamente)
const { $api } = createEcfFrontendReactClient({
getToken: async () => {
const res = await fetch('/api/v1/ecf-token');
const { apiKey } = await res.json();
return apiKey;
},
environment: 'prod',
});
// 2. Enviar la factura al backend
function EnviarFactura() {
const handleSubmit = async (invoiceData) => {
const res = await fetch('/api/v1/invoices', {
method: 'POST',
body: JSON.stringify(invoiceData),
});
const { messageId, rnc, encf } = await res.json();
// El cliente no espera — navega a la página de estado
navigate(`/ecf-status/${rnc}/${encf}`);
};
}
// 3. Polling automático del estado del ECF
function EstadoEcf({ rnc, encf }: { rnc: string; encf: string }) {
const { data } = $api.useQuery('get', '/ecf/{rnc}/{encf}', {
params: { path: { rnc, encf } },
refetchInterval: 3000,
});
if (data?.progress === 'Finished') {
return (
<div>
<p>Comprobante aceptado</p>
<p>Código seguridad: {data.codSec}</p>
<QRCode value={data.impresionUrl} />
</div>
);
}
return <p>Procesando... ({data?.progress})</p>;
}Además de enviar comprobantes, los SDKs exponen todos los endpoints del API:
| Funcionalidad | Descripción |
|---|---|
| Empresas | Crear, consultar y eliminar empresas registradas |
| Certificados | Subir y consultar certificados digitales |
| Consulta de e-CF | Buscar comprobantes por RNC, eNCF, fecha, monto, etc. |
| Aprobación Comercial | Enviar aprobación/rechazo comercial (ACECF) |
| Anulación de Rangos | Solicitar anulación de secuencias de eNCF |
| Consultas DGII | Directorio, estado, resultado, timbre, RFCE, track IDs |
| Estatus de Servicios | Verificar disponibilidad de servicios DGII |
| Ventanas de Mantenimiento | Consultar ventanas de mantenimiento programadas |
| API Keys | Crear API keys para acceso programático |
Cada SDK tiene su propia documentación con ejemplos específicos:
| SDK | Documentación |
|---|---|
| .NET | .net/README.md |
| TypeScript | typescript/README.md |
| Python | python/README.md |
| PHP | ecf-dgii-php |
| Java | java/README.md |
| Kotlin | kotlin/README.md |
| iOS/Swift | ios/README.md |
| C++ | C++/README.md |
| React | react/README.md |
Si usabas los paquetes SSDDO.ECF_DGII.Models y SSDDO.ECF_DGII.SDK v1/v2, consulta la guía de migración en el README de .NET.
En resumen: ya no necesitas implementar firmado XML, autenticación por semilla, manejo de certificados, ni reintentos. Todo eso lo hace ECF SSD.
El repositorio incluye colecciones abiertas de Bruno (open source) para probar el API directamente sin escribir código:
| Colección | Archivo | Descripción |
|---|---|---|
| ECF DGII API | bruno/ecf-dgii-api.json |
API principal — comprobantes, empresas, certificados, DGII, etc. |
| ECF Recepcion API | bruno/ecf-recepcion-api.json |
API de recepción emisor-receptor |
- Instala Bruno
- Abre Bruno y selecciona Import Collection
- Selecciona Bruno Collection e importa el archivo
.jsondeseado - Selecciona el ambiente (Test, Cert, o Prod)
- Configura tu API Key en las variables del ambiente
- Envía requests
Cada colección incluye 3 ambientes preconfigurados (Test, Cert, Prod) con las URLs correctas.
- Documentación: https://ecf.ssd.com.do
- Issues: GitHub Issues
🇩🇴 Hecho con plátano power
© Smart Software Development SSD SRL 2026
