MSeller LogoECF MSeller
🔍
Integración

Anulación de e-NCF

Anular rangos de secuencias de e-NCF no utilizadas ante la DGII desde MSeller ECF

Anulación de e-NCF

Cuando una empresa deja de utilizar secuencias de e-NCF que la DGII le autorizó —porque cambió de sistema, porque se saltaron secuencias, o porque un rango quedó reservado y nunca se emitió— debe anularlas para que no queden pendientes de reporte.

MSeller ECF expone un endpoint que recibe los rangos en JSON, construye el documento de anulación (ANECF) según el formato de la DGII, lo firma con el certificado digital de la cuenta y lo envía al servicio de anulación de rangos. También existe una herramienta en el portal (Herramientas → Anular e-NCF) que hace exactamente lo mismo sin escribir código.

⚠️ IMPORTANTE: La anulación es irreversible. Una vez que la DGII acepta el documento, esas secuencias no pueden volver a emitirse. Anule únicamente secuencias que no hayan sido utilizadas.

Endpoint

POST /{entorno}/customer/void-ncf

Donde {entorno} puede ser:

  • TesteCF (para pruebas)
  • CerteCF (para certificación)
  • eCF (para producción)

Encabezados requeridos

Authorization: Bearer {tu_idToken}
Content-Type: application/json

Este endpoint no requiere API Key: se autentica con el idToken obtenido en Autenticación API.

Requisitos previos

  • Tener un certificado digital (.p12) activo cargado en la plataforma. El RNC emisor se toma del token, nunca del cuerpo de la solicitud.
  • Que las secuencias pertenezcan a rangos autorizados al RNC que hace la solicitud.

Cuerpo de la solicitud

{
  "ranges": [
    { "secuenciaDesde": "E310000000001", "secuenciaHasta": "E310000000010" },
    { "secuenciaDesde": "E310000000020", "secuenciaHasta": "E310000000020" },
    { "secuenciaDesde": "E320000000001", "secuenciaHasta": "E320000000005" }
  ]
}
CampoTipoRequeridoDescripción
rangesarrayLista de rangos a anular. Debe contener al menos un elemento.
ranges[].secuenciaDesdestringe-NCF que inicia el rango (13 posiciones). Ej.: E310000000001.
ranges[].secuenciaHastastringe-NCF que cierra el rango. Misma serie y tipo que secuenciaDesde, y mayor o igual que este.
ranges[].tipoeCFstringNoVerificación opcional. Si se envía, debe coincidir con el tipo codificado dentro del propio e-NCF.
fechaHoraAnulacionstringNoFormato dd-MM-aaaa HH:mm:ss. Si se omite, se usa la hora actual de República Dominicana.

Para anular una sola secuencia, envíe el mismo e-NCF en secuenciaDesde y secuenciaHasta.

El RNC emisor, los números de línea, la cantidad por tipo y el total del encabezado los calcula MSeller ECF; no se envían en la solicitud.

Agrupación por tipo de e-CF

Los rangos se agrupan automáticamente por tipo de comprobante: todos los rangos de un mismo tipo terminan dentro de un solo bloque <Anulacion>. La DGII acepta hasta 10 bloques (uno por cada tipo de e-CF) y hasta 10,000 rangos por bloque.

Tipos de e-CF admitidos:

TipoComprobanteTipoComprobante
31Factura de Crédito Fiscal43Gastos Menores
32Factura de Consumo44Regímenes Especiales
33Nota de Débito45Gubernamental
34Nota de Crédito46Comprobante para Exportaciones
41Compras47Comprobante para Pagos al Exterior

XML generado (ANECF)

El JSON del ejemplo anterior produce el siguiente documento, que MSeller ECF firma antes de enviarlo a la DGII:

<?xml version="1.0" encoding="utf-8"?>
<ANECF>
  <Encabezado>
    <Version>1.0</Version>
    <RncEmisor>130862346</RncEmisor>
    <CantidadeNCFAnulados>16</CantidadeNCFAnulados>
    <FechaHoraAnulacioneNCF>18-08-2026 10:15:00</FechaHoraAnulacioneNCF>
  </Encabezado>
  <DetalleAnulacion>
    <Anulacion>
      <NoLinea>1</NoLinea>
      <TipoeCF>31</TipoeCF>
      <TablaRangoSecuenciasAnuladaseNCF>
        <Secuencias>
          <SecuenciaeNCFDesde>E310000000001</SecuenciaeNCFDesde>
          <SecuenciaeNCFHasta>E310000000010</SecuenciaeNCFHasta>
        </Secuencias>
        <Secuencias>
          <SecuenciaeNCFDesde>E310000000020</SecuenciaeNCFDesde>
          <SecuenciaeNCFHasta>E310000000020</SecuenciaeNCFHasta>
        </Secuencias>
      </TablaRangoSecuenciasAnuladaseNCF>
      <CantidadeNCFAnulados>11</CantidadeNCFAnulados>
    </Anulacion>
    <Anulacion>
      <NoLinea>2</NoLinea>
      <TipoeCF>32</TipoeCF>
      <TablaRangoSecuenciasAnuladaseNCF>
        <Secuencias>
          <SecuenciaeNCFDesde>E320000000001</SecuenciaeNCFDesde>
          <SecuenciaeNCFHasta>E320000000005</SecuenciaeNCFHasta>
        </Secuencias>
      </TablaRangoSecuenciasAnuladaseNCF>
      <CantidadeNCFAnulados>5</CantidadeNCFAnulados>
    </Anulacion>
  </DetalleAnulacion>
  <Signature>...</Signature>
</ANECF>

Estructura del formato

Encabezado

CampoDescripciónTipoLargo
VersionVersión del formato de anulación. Valor fijo 1.0.NUM3
RncEmisorRNC del contribuyente que emite la anulación.NUM9 u 11
CantidadeNCFAnuladosSumatoria de e-NCF anulados en todo el detalle.NUM10
FechaHoraAnulacioneNCFFecha y hora de generación, en formato dd-MM-aaaa HH:mm:ss.ALFANUM19

Detalle de anulación (bloque Anulacion, hasta 10 repeticiones)

CampoDescripciónTipoLargo
NoLineaNúmero de línea del bloque, de 1 a 10.NUM2
TipoeCFTipo de comprobante fiscal electrónico.NUM2
TablaRangoSecuenciasAnuladaseNCFTabla de rangos consecutivos. Hasta 10,000 repeticiones.
Secuencias.SecuenciaeNCFDesdee-NCF que inicia el rango. Ej.: E310000000001.ALFANUM13
Secuencias.SecuenciaeNCFHastae-NCF que cierra el rango. Misma serie y tipo, mayor o igual al inicial.ALFANUM13
CantidadeNCFAnuladosCantidad de secuencias anuladas en el bloque.NUM10

Firma digital — el bloque <Signature> se genera automáticamente con el certificado de la cuenta.

Nota: La estructura del e-NCF es: una serie entre E y Z (se exceptúa la P), el tipo de comprobante en 2 dígitos y el secuencial en 10 dígitos. En total, 13 posiciones.

Respuestas

Anulación aceptada — 200

{
  "message": "Rangos de e-NCF anulados correctamente.",
  "voidId": "7c0a1d4e-2f6b-4a2c-9a51-8f2c9b3d1e42",
  "status": "Aceptado",
  "rnc": "130862346",
  "fechaHoraAnulacion": "18-08-2026 10:15:00",
  "totalVoided": 16,
  "ranges": [
    {
      "tipoeCF": "31",
      "secuenciaDesde": "E310000000001",
      "secuenciaHasta": "E310000000010",
      "cantidad": 10
    },
    {
      "tipoeCF": "31",
      "secuenciaDesde": "E310000000020",
      "secuenciaHasta": "E310000000020",
      "cantidad": 1
    },
    {
      "tipoeCF": "32",
      "secuenciaDesde": "E320000000001",
      "secuenciaHasta": "E320000000005",
      "cantidad": 5
    }
  ],
  "fileName": "130862346-ANECF-7c0a1d4e-2f6b-4a2c-9a51-8f2c9b3d1e42.xml",
  "dgiiResponse": {
    "codigo": "1",
    "nombre": "Aceptado",
    "mensajes": []
  }
}

Guarde el voidId: es la referencia con la que puede consultar la anulación más adelante.

Anulación rechazada por la DGII — 422

La solicitud llegó a la DGII, pero fue rechazada. El motivo viene en dgiiResponse.mensajes y el intento queda registrado igualmente.

{
  "message": "La DGII rechazó la anulación.",
  "voidId": "7c0a1d4e-2f6b-4a2c-9a51-8f2c9b3d1e42",
  "status": "Rechazado",
  "totalVoided": 16,
  "dgiiResponse": {
    "codigo": "2",
    "nombre": "Rechazado",
    "mensajes": ["La secuencia E310000000005 ya fue utilizada"]
  }
}

Errores de validación — 400

Los rangos se validan antes de firmar y enviar nada, de modo que un error de captura nunca consume una llamada a la DGII.

codeCausa
MISSING_RANGESranges ausente o vacío.
MISSING_SEQUENCEFalta secuenciaDesde o secuenciaHasta en una línea.
INVALID_ENCF_LENGTHEl e-NCF no tiene 13 posiciones.
INVALID_ENCF_FORMATSerie fuera del rango EZ (la serie P está reservada) o dígitos inválidos.
SERIE_MISMATCHLos dos extremos del rango usan series distintas.
TIPO_MISMATCHLos extremos son de tipos distintos, o tipoeCF contradice al e-NCF.
INVALID_TIPO_ECFEl tipo no está entre 31, 32, 33, 34, 41, 43, 44, 45, 46 y 47.
INVALID_SEQUENCEEl secuencial es cero.
INVALID_RANGE_ORDEREl e-NCF "hasta" es menor que el "desde".
OVERLAPPING_RANGESDos líneas se solapan para la misma serie y tipo.
TOO_MANY_TIPOSMás de 10 tipos de e-CF en una misma solicitud.
TOO_MANY_RANGESMás de 10,000 rangos para un mismo tipo.
{
  "message": "En la línea 2 el e-NCF \"hasta\" (E310000000001) debe ser mayor o igual que el e-NCF \"desde\" (E310000000010).",
  "code": "INVALID_RANGE_ORDER"
}

Otros errores

Código HTTPcodeSignificado
400EMPTY_BODY, INVALID_JSONEl cuerpo está vacío o no es JSON válido.
401UNAUTHORIZEDToken ausente, expirado o inválido.
412CERTIFICATE_NOT_CONFIGUREDNo hay certificado activo. Cárguelo y vuelva a iniciar sesión.
500CERTIFICATE_UNAVAILABLEEl certificado no pudo cargarse.
500SIGN_ERRORFalló la firma del documento de anulación.
502DGII_AUTH_ERRORNo fue posible autenticar contra la DGII.
502DGII_VOID_ERROREl servicio de anulación de la DGII no respondió correctamente.

Consulta de anulaciones

Todas las anulaciones quedan registradas, tanto las aceptadas como las rechazadas y las que fallaron en tránsito.

GET /{entorno}/customer/void-ncf
GET /{entorno}/customer/void-ncf?voidId={voidId}
ParámetroDescripción
voidIdDevuelve una sola anulación (404 si no existe).
statusFiltra por Aceptado, Rechazado o Error.
fromDateFecha inicial en milisegundos epoch.
toDateFecha final en milisegundos epoch.
limitEntre 1 y 100. Por defecto 25.
nextTokenCursor devuelto por la página anterior.
{
  "items": [
    {
      "voidId": "7c0a1d4e-2f6b-4a2c-9a51-8f2c9b3d1e42",
      "customerId": "130862346",
      "createdAt": 1787062500000,
      "updateAt": 1787062503000,
      "status": "Aceptado",
      "environment": "TesteCF",
      "fechaHoraAnulacion": "18-08-2026 10:15:00",
      "totalVoided": 16,
      "ranges": [
        {
          "tipoeCF": "31",
          "secuenciaDesde": "E310000000001",
          "secuenciaHasta": "E310000000010",
          "cantidad": 10
        }
      ],
      "fileName": "130862346-ANECF-7c0a1d4e-2f6b-4a2c-9a51-8f2c9b3d1e42.xml",
      "dgiiCode": "1",
      "dgiiName": "Aceptado",
      "dgiiResponse": []
    }
  ],
  "nextToken": "eyJjdXN0b21lcklkIjoi...",
  "metadata": { "itemsPerPage": 25 }
}

Los resultados vienen del más reciente al más antiguo y siempre corresponden al RNC del token.

Estados

EstadoSignificado
AceptadoLa DGII aceptó la anulación. Las secuencias ya no pueden emitirse.
RechazadoLa DGII recibió el documento y lo rechazó. El motivo está en dgiiResponse.
ErrorEl documento no llegó a la DGII, o llegó pero su respuesta no pudo confirmarse.

⚠️ Antes de reintentar un Error: este estado no garantiza que la anulación no se haya procesado. El endpoint no es idempotente: cada solicitud genera un voidId nuevo y envía un documento nuevo a la DGII, así que reintentar a ciegas puede anular dos veces el mismo rango.

Consulte primero GET /{entorno}/customer/void-ncf?voidId={voidId} con el voidId que devolvió la solicitud fallida:

  • Si pasó a Aceptado o Rechazado, la DGII ya respondió — no reintente.
  • Si sigue en Error, verifique el estado real de las secuencias en la DGII antes de enviar una nueva solicitud.

Si recibió una respuesta 400 de validación o 401 de autenticación, la solicitud se rechazó antes de construir el documento: no se envió nada a la DGII y puede corregir y reenviar sin riesgo.

No asuma lo mismo cuando no hubo respuesta HTTP. Un timeout o una conexión cortada puede ocurrir después de que la anulación se envió a la DGII, aunque usted nunca haya recibido el voidId. En ese caso consulte el historial (GET /{entorno}/customer/void-ncf) y verifique el estado de las secuencias antes de enviar otra solicitud.

Ejemplos completos

curl -X POST "https://ecf.api.mseller.app/TesteCF/customer/void-ncf" \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ranges": [
      { "secuenciaDesde": "E310000000001", "secuenciaHasta": "E310000000010" },
      { "secuenciaDesde": "E320000000001", "secuenciaHasta": "E320000000005" }
    ]
  }'
const response = await fetch('https://ecf.api.mseller.app/TesteCF/customer/void-ncf', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${idToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    ranges: [
      { secuenciaDesde: 'E310000000001', secuenciaHasta: 'E310000000010' },
      { secuenciaDesde: 'E320000000001', secuenciaHasta: 'E320000000005' }
    ]
  })
})

const result = await response.json()

if (result.status === 'Aceptado') {
  console.log(`Se anularon ${result.totalVoided} secuencias. Referencia: ${result.voidId}`)
} else {
  console.error('La DGII no aceptó la anulación:', result.dgiiResponse?.mensajes)
}
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", idToken);

var payload = new
{
    ranges = new[]
    {
        new { secuenciaDesde = "E310000000001", secuenciaHasta = "E310000000010" },
        new { secuenciaDesde = "E320000000001", secuenciaHasta = "E320000000005" }
    }
};

var content = new StringContent(
    JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");

var response = await client.PostAsync(
    "https://ecf.api.mseller.app/TesteCF/customer/void-ncf", content);

var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
$payload = [
    'ranges' => [
        ['secuenciaDesde' => 'E310000000001', 'secuenciaHasta' => 'E310000000010'],
        ['secuenciaDesde' => 'E320000000001', 'secuenciaHasta' => 'E320000000005'],
    ],
];

$ch = curl_init('https://ecf.api.mseller.app/TesteCF/customer/void-ncf');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . $idToken,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
curl_close($ch);

print_r(json_decode($response, true));

Herramienta del portal

Si prefiere no integrar el endpoint, el portal incluye la herramienta Herramientas → Anular e-NCF:

  1. Seleccione el entorno (TesteCF, CerteCF o eCF).
  2. Capture los rangos línea por línea, o pegue varias líneas de una hoja de cálculo con el botón Pegar varias líneas (un rango por línea, desde y hasta separados por tabulación, coma o espacio).
  3. Revise el documento con Ver XML antes de enviarlo.
  4. Confirme la anulación. El resultado y el historial completo de anulaciones quedan visibles en la misma pantalla.

Cada línea se valida mientras se escribe: el tipo de e-CF y la cantidad de secuencias se derivan del propio e-NCF, y los rangos solapados se señalan antes de enviar.

Buenas prácticas

  • Verifique antes de anular. Consulte primero el estado de las secuencias con Consulta de Documentos; si una secuencia ya se emitió, la DGII rechazará el bloque completo.
  • Pruebe en TesteCF. El flujo es idéntico al de producción y no consume secuencias reales.
  • Anule por rangos, no una a una. Un rango de 500 secuencias es una sola línea, y la DGII lo procesa mucho más rápido que 500 rangos individuales.
  • Guarde el voidId en su sistema junto con las secuencias afectadas; es la evidencia de la anulación ante cualquier revisión.