Catálogo de eventos
El sobre (envelope)
Sección titulada «El sobre (envelope)»Toda entrega llega con la misma forma exterior, sin importar el evento:
{ "id": "evt_018f3c2a1e6b7d40a5c8e1d2b3a4f506", "object": "event", "type": "ecf.accepted", "apiVersion": "1", "createdAt": "2026-09-07T14:03:11-04:00", "data": { "object": { "...": "el recurso afectado" } }}| Campo | Nota |
|---|---|
id |
Único por evento. Es tu clave para deduplicar (ver Verificar firma). |
object |
Siempre "event". |
type |
El tipo de evento, por ejemplo ecf.accepted. |
apiVersion |
Versión del formato del sobre, hoy "1". |
createdAt |
Hora dominicana, como todo lo que emite la API. |
data.object |
El recurso afectado. Salvo que se indique lo contrario abajo, tiene la misma forma que el GET correspondiente. |
Te suscribes a un tipo exacto, a una categoría completa con comodín
(ecf.* cubre los 6 del ciclo de vida más ecf.duplicate_suspected), o a
todo con *.
Ciclo de vida del e-CF
Sección titulada «Ciclo de vida del e-CF»| Evento | Cuándo se dispara |
|---|---|
ecf.submitted |
La DGII recibió el comprobante y devolvió un TrackId. Se repite si NovaFE reenvía el comprobante. |
ecf.accepted |
La DGII lo aceptó: fiscalmente válido. |
ecf.accepted_conditional |
Aceptado con una observación, igualmente válido. |
ecf.rejected |
La DGII lo rechazó de forma definitiva. |
ecf.review |
La DGII no resolvió tras el ladder de consultas. |
ecf.failed |
Falló el transporte tras agotar los reintentos. |
ecf.rejected solo se emite cuando el rechazo es definitivo. Si la DGII falla
de forma pasajera y NovaFE reenvía el comprobante por su cuenta, no se emite
mientras dure el reintento; se emite únicamente si los reintentos se agotan. Ver
Rechazos y reintentos.
data.object es el mismo EcfDto que devuelve
GET /ecf/{id}. No existe un evento
ecf.signed: ese estado ya lo tienes en la respuesta de POST /ecf. Si tu
cuenta no espera el resultado de la DGII al emitir, el primer evento que
recibirás de cada comprobante es ecf.submitted.
Duplicado sospechado
Sección titulada «Duplicado sospechado»| Evento | Cuándo se dispara |
|---|---|
ecf.duplicate_suspected |
Con el modo observar de detección de duplicados, el e-CF se emitió igualmente pero coincidió en huella con uno reciente. |
Este es uno de los dos eventos cuyo data.object no es directamente
el recurso, sino una estructura propia:
{ "ecf": { "...": "EcfDto" }, "previousEcfId": "...", "previousEncf": "E310000000010"}Ver Endpoints y semántica para el detalle completo de cómo funciona la detección por huella.
Recepción B2B
Sección titulada «Recepción B2B»| Evento | Cuándo se dispara |
|---|---|
inbound_ecf.received |
Recibiste un e-CF de otro contribuyente y le devolviste el ARECF firmado, lo hayas aceptado o rechazado. |
commercial_approval.received |
Un comprador externo aprobó o rechazó comercialmente un e-CF tuyo. |
Ver Recibir un e-CF.
Vencimientos
Sección titulada «Vencimientos»| Evento | Cuándo se dispara |
|---|---|
certificate.expiring |
Tu certificado activo se acerca a su vencimiento (90, 30, 15 o 7 días antes). |
certificate.expired |
Tu certificado venció. |
sequence.expiring |
Un rango de e-NCF se acerca a su vencimiento (30 o 7 días antes). |
sequence.expired |
Un rango venció. |
sequence.low |
Un rango cayó al 20 % o menos de su stock. |
sequence.exhausted |
Un rango se quedó sin números por entregar. |
Ver e-NCF y secuencias.
Contingencia
Sección titulada «Contingencia»| Evento | Cuándo se dispara |
|---|---|
contingency.activated |
NovaFE entra en modo de contingencia (automático o manual). |
contingency.deactivated |
Sale del modo de contingencia. |
data.object es { status: "active" | "inactive", changedAt, oldestPendingMinutes }.
A diferencia del resto, no es un evento de tu tenant puntual: se emite a
todos los tenants suscritos por igual, porque la contingencia es un estado
de la plataforma completa, no de un comprobante o de una cuenta.
Pausa de emisión
Sección titulada «Pausa de emisión»| Evento | Cuándo se dispara |
|---|---|
tenant.emission_paused |
Tú o tu organización pausaron la emisión de comprobantes nuevos. |
tenant.emission_resumed |
Se levantó la pausa a mano. |
data.object es { tenantId, paused, reason, until, source, changedBy, organizationId }, donde
source es tenant u organization. Solo avisan cuando el estado efectivo cambia: cambiar
únicamente el motivo no genera otro evento, y una pausa que termina sola por su hora de
reanudación tampoco genera uno. Mientras la emisión está pausada, POST /ecf responde 409 con el
código Ecf.EmissionPaused; lo ya firmado, los reintentos, la validación y las consultas siguen
funcionando.
Alertas
Sección titulada «Alertas»| Evento | Cuándo se dispara |
|---|---|
alert.rejection_spike |
El porcentaje de comprobantes rechazados en la última hora llegó a tu umbral. |
alert.emission_silence |
Pasaron las horas laborales que configuraste sin que emitieras ningún comprobante. |
Las dos alertas están apagadas hasta que las configures (alerts.rejection_rate_threshold_pct,
alerts.no_emission_hours y alerts.business_hours). Se evalúan cada 15 minutos.
alert.rejection_spike: data.object es { tenantId, windowMinutes, total, rejected, ratePct, thresholdPct }. Necesita al menos 5 comprobantes en la última hora, para que un solo rechazo no
cuente como un 100 %, y se repite a lo sumo cada 6 horas mientras el pico siga en pie.
alert.emission_silence: data.object es { tenantId, lastEmissionAt, silentHours, thresholdHours }.
Solo cuenta el tiempo dentro de tu horario laboral y avisa una sola vez por silencio: vuelve a avisar
únicamente después de que emitas un comprobante nuevo. No avisa fuera del horario laboral, mientras la
emisión está pausada, ni a un contribuyente que todavía no ha emitido nunca.
Tope mensual de emisión
Sección titulada «Tope mensual de emisión»| Evento | Cuándo se dispara |
|---|---|
tenant.monthly_limit_warning |
Tu emisión de Producción del mes llegó al 80 % del tope mensual. |
tenant.monthly_limit_reached |
Llegó al 100 %: los comprobantes nuevos se rechazan hasta el mes siguiente. |
data.object es { tenantId, period, limit, used }, donde period es el mes (yyyy-MM). Cada
umbral avisa una sola vez por mes. Mientras el tope está alcanzado, POST /ecf responde 409 con
el código Ecf.MonthlyLimitReached.
Uso y facturación
Sección titulada «Uso y facturación»| Evento | Cuándo se dispara |
|---|---|
usage.threshold_reached |
Tu organización consumió el 80 % de su cupo incluido de e-CF del período. |
usage.limit_reached |
Consumió el 100 % de e-CF. |
usage.tenant_threshold_reached |
El pico de tenants del período llegó al 80 % de tu cupo. |
usage.tenant_limit_reached |
El pico de tenants llegó al 100 %. |
usage.member_threshold_reached |
El pico de miembros de la organización llegó al 80 % de tu cupo. |
usage.member_limit_reached |
El pico de miembros llegó al 100 %. |
billing.period_closed |
Se cerró un período de facturación, con el resumen de las tres dimensiones. |
Los cuatro primeros son el mismo aviso proactivo de excedente que describe Planes y precios, solo que por webhook en vez de tener que consultarlo tú.
El evento de prueba
Sección titulada «El evento de prueba»webhook.ping no es un evento real de tu cuenta: es el que dispara
POST /webhooks/{id}/ping para que pruebes un
endpoint. No te puedes suscribir a él, y nunca llega por ninguna otra vía.