Trazza — API de Facturación Electrónica DIAN

Sistema de facturación electrónica colombiana como integrador propio ante la DIAN. Emita facturas, notas crédito/débito, documentos soporte y notas de ajuste cumpliendo la normativa vigente (Anexo Técnico v1.9, Resolución 000165 de 2023).

REST API UBL 2.1 XAdES-EPES Multi-tenant

URL Base

URL
https://su-dominio.com/api/v1

Probar endpoints en vivo (Swagger UI)

La API incluye una interfaz interactiva donde puede explorar y probar endpoints directamente desde el navegador, sin necesidad de Postman ni herramientas externas.

URL
https://su-dominio.com/api/docs

Cómo usarlo:

  1. Abra la URL en su navegador
  2. Haga click en "Authorize" (candado arriba a la derecha) y pegue su token JWT
  3. Seleccione cualquier endpoint y haga click en "Try it out"
  4. Edite los parámetros o el body JSON si lo desea
  5. Haga click en "Execute" para enviar la petición y ver la respuesta
Nota
Swagger UI requiere un token JWT válido para operar endpoints protegidos. Sin autenticarse, solo podrá consultar endpoints públicos (catálogos DIAN, estado del servicio).
Modo solo lectura en producción
En el ambiente de producción, Swagger UI funciona en modo solo lectura parcial: el botón "Try it out" solo está disponible en endpoints GET (consultas). Los métodos POST, PUT y DELETE están deshabilitados para prevenir la creación accidental de facturas u otros documentos reales ante la DIAN. Para operar en producción, use Postman o su integración directa.

Documentos soportados

TipoCódigoCódigo únicoDescripción
Factura de venta01CUFE (SHA-384)Factura electrónica estándar
Factura exportación02CUFEOperaciones de exportación
Factura contingencia (talonario)03CUFEModo contingencia manual
Factura contingencia (DIAN)04CUFEModo contingencia electrónico
Factura mandato01 (tipoOperacion=11)CUFE (SHA-384)Mandatario factura a nombre de mandante
Documento soporte05CUDS (SHA-384)Adquisiciones a no obligados
Nota crédito91CUDE (SHA-384)Ajustes a favor del comprador
Nota débito92CUDE (SHA-384)Ajustes a favor del vendedor
Nota de ajuste95CUDS (SHA-384)Ajustes al documento soporte

Flujo general

  1. Autenticarse — Obtenga un token JWT mediante el endpoint de login.
  2. Configurar empresa — Registre los datos fiscales, certificado digital .p12 y credenciales DIAN.
  3. Crear rangos de numeración — Configure las resoluciones de numeración autorizadas por la DIAN.
  4. Emitir documentos — Cree facturas, notas crédito/débito o documentos soporte. El sistema genera el XML UBL 2.1, calcula CUFE/CUDE/CUDS, firma con XAdES-EPES y genera el QR.
  5. Enviar a DIAN — Envíe el documento firmado al servicio web de la DIAN y consulte su estado.

Autenticación

La API usa autenticación JWT Bearer Token. Incluya el token en el header Authorization de cada petición.

Login

POST/api/v1/auth/login
Rate limit
El endpoint de login permite máximo 5 peticiones cada 15 minutos por dirección IP.

Request

json
{
  "email": "admin@empresa.com",
  "password": "suContraseña"
}

Response 200

json
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "usuario": {
    "id": "507f1f77bcf86cd799439011",
    "email": "admin@empresa.com",
    "nombre": "Administrador",
    "rol": "admin"
  }
}

Usar el token

bash
curl -X GET https://su-dominio.com/api/v1/documentos \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json"
Importante
El token JWT contiene userId, empresaId y rol. Todas las operaciones se limitan automáticamente a la empresa asociada al token — no es posible acceder a datos de otra empresa.

Roles

RolAccesoDescripción
adminSu empresaGestión completa de la empresa: configuración, certificados, documentos, usuarios
usuarioSu empresaCrear y consultar documentos electrónicos

Registrar usuarios

POST/api/v1/auth/registrar

Requiere rol admin. Permite crear usuarios dentro de su empresa.

json
{
  "email": "usuario@empresa.com",
  "password": "minimo6caracteres",
  "nombre": "Juan Pérez",
  "rol": "usuario"
}

Configuración Inicial

Antes de emitir documentos electrónicos, debe configurar su empresa con los datos fiscales y las credenciales de la DIAN.

Crear empresa

POST/api/v1/empresas

Requiere rol admin. Al crear la empresa, su usuario queda vinculado automáticamente.

json
{
  "tipoIdentificacion": "31",
  "numeroIdentificacion": "900123456",
  "digitoVerificacion": "7",
  "razonSocial": "Mi Empresa S.A.S.",
  "nombreComercial": "Mi Empresa",
  "tipoOrganizacion": "1",
  "responsabilidadesFiscales": ["O-13"],
  "codigoTributo": "01",
  "direccion": {
    "codigoMunicipio": "11001",
    "nombreCiudad": "Bogotá",
    "codigoDepartamento": "11",
    "nombreDepartamento": "Cundinamarca",
    "codigoPais": "CO",
    "nombrePais": "Colombia",
    "direccionLinea": "Calle 100 # 15-20",
    "codigoPostal": "110111"
  },
  "contacto": {
    "telefono": "3001234567",
    "email": "contacto@miempresa.com",
    "nombre": "Contacto Empresa"
  },
  "dianAmbiente": 2,
  "dianSoftwareId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "dianSoftwarePin": "12345",
  "dianTestSetId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Ambientes DIAN
dianAmbiente: 2 = Habilitación (pruebas) — use este mientras se certifica.
dianAmbiente: 1 = Producción — se activa automáticamente al completar la habilitación.

Campos principales

tipoIdentificacionrequeridostring
Código DIAN de tipo de identificación. Ej: "31" para NIT.
numeroIdentificacionrequeridostring
NIT o número de identificación sin dígito de verificación.
digitoVerificacionrequeridostring
Dígito de verificación (un solo dígito).
razonSocialrequeridostring
Razón social registrada ante la DIAN.
tipoOrganizacionrequeridostring
"1" = Persona jurídica, "2" = Persona natural.
responsabilidadesFiscalesrequeridostring[]
Ej: ["O-13"] para Gran contribuyente, ["O-15"] para Autorretenedor, ["R-99-PN"] para No aplica.
dianSoftwareIdrequeridostring
UUID del software registrado ante la DIAN.
dianSoftwarePinrequeridostring
PIN del software DIAN. Se almacena encriptado (AES-256-GCM).
dianTestSetIdopcionalstring
UUID del test set para habilitación.

Subir certificado digital (.p12)

POST/api/v1/empresas/:id/certificado

Suba el certificado digital en formato .p12 / .pfx. Límite: 5 MB.

bash
curl -X POST https://su-dominio.com/api/v1/empresas/EMPRESA_ID/certificado \
  -H "Authorization: Bearer TOKEN" \
  -F "certificado=@/ruta/certificado.p12" \
  -F "password=claveCertificado"

Actualizar empresa

PUT/api/v1/empresas/:id

Solo incluya los campos que desea modificar.

Consultar empresa

GET/api/v1/empresas/:id

Los campos sensibles (certificado, passwords, PINs) nunca se incluyen en la respuesta.

Numeración

Registre los rangos de numeración autorizados por la DIAN para su empresa. Cada tipo de documento (facturas, notas, etc.) necesita su propio rango.

Crear rango de numeración

POST/api/v1/numeracion
json
{
  "tipo": "01",
  "prefijo": "FACT",
  "rangoInicio": 1,
  "rangoFin": 99999,
  "resolucion": "18764050289527",
  "fechaInicio": "2024-01-01",
  "fechaFin": "2026-12-31"
}

Listar numeraciones

GET/api/v1/numeracion

Parámetros de consulta

tipoopcionalstring
Filtrar por tipo de documento. Ej: "01" para facturas.

Verificar disponibilidad

GET/api/v1/numeracion/disponibilidad
bash
curl -G https://su-dominio.com/api/v1/numeracion/disponibilidad \
  -H "Authorization: Bearer TOKEN" \
  --data-urlencode "tipo=01" \
  --data-urlencode "prefijo=FACT"

Consultar rangos DIAN

GET/api/v1/numeracion/rangos-dian

Consulta directamente los rangos autorizados en la DIAN para su empresa.

Desactivar numeración

DELETE/api/v1/numeracion/:id

Facturas

Cree facturas electrónicas de venta (01), exportación (02), contingencia talonario (03) o contingencia DIAN (04). El sistema genera automáticamente el XML UBL 2.1, calcula el CUFE, firma con XAdES-EPES y genera el código QR.

POST/api/v1/facturas
Rate limit
Máximo 30 peticiones cada 15 minutos para creación de documentos.
Datos del emisor
Los datos del emisor se toman automáticamente de la configuración de su empresa. No es necesario incluirlos en el request.
Precisión de valores monetarios
Todos los valores monetarios deben enviarse con exactamente 2 decimales (ej: 1000000.00, no 1000000), conforme al Anexo Técnico DIAN v1.9.

Reglas de consistencia obligatorias:
valorTotal de cada línea = cantidad × valorUnitario
impuestos[].valor de cada línea = baseImponible × porcentaje / 100
• Los impuestos totalizados a nivel de documento deben ser la suma exacta de los impuestos de todas las líneas del mismo código de tributo
totalSinImpuestos = suma de todos los valorTotal de las líneas
totalPagar = totalSinImpuestos + totalImpuestos - totalDescuentos + totalCargos

Si los valores no cuadran, la DIAN rechazará el documento.

Ejemplo completo

json
{
  "tipo": "01",
  "prefijo": "FACT",
  "numero": 1001,
  "fechaEmision": "2026-03-02",
  "horaEmision": "10:30:00-05:00",
  "fechaVencimiento": "2026-04-02",
  "moneda": "COP",
  "enviarEmail": true,

  "adquirente": {
    "tipoOrganizacion": "1",
    "tipoIdentificacion": "31",
    "numeroIdentificacion": "800987654",
    "digitoVerificacion": "3",
    "razonSocial": "Cliente S.A.",
    "email": "compras@cliente.com",
    "responsabilidadesFiscales": ["R-99-PN"],
    "codigoTributo": "01",
    "direccion": {
      "codigoMunicipio": "76001",
      "nombreCiudad": "Cali",
      "codigoDepartamento": "76",
      "nombreDepartamento": "Valle del Cauca",
      "codigoPais": "CO",
      "nombrePais": "Colombia",
      "direccionLinea": "Avenida 5N # 23-45"
    }
  },

  "lineas": [
    {
      "numero": 1,
      "descripcion": "Servicio de consultoría",
      "cantidad": 1,
      "unidadMedida": "94",
      "valorUnitario": 1000000.00,
      "valorTotal": 1000000.00,
      "impuestos": [
        {
          "codigo": "01",
          "nombre": "IVA",
          "porcentaje": 19,
          "baseImponible": 1000000.00,
          "valor": 190000.00
        }
      ]
    },
    {
      "numero": 2,
      "descripcion": "Licencia de software mensual",
      "cantidad": 3,
      "unidadMedida": "94",
      "valorUnitario": 500000.00,
      "valorTotal": 1500000.00,
      "impuestos": [
        {
          "codigo": "01",
          "nombre": "IVA",
          "porcentaje": 19,
          "baseImponible": 1500000.00,
          "valor": 285000.00
        }
      ]
    }
  ],

  "impuestos": [
    {
      "codigo": "01",
      "nombre": "IVA",
      "porcentaje": 19,
      "baseImponible": 2500000.00,
      "valor": 475000.00
    }
  ],

  "totales": {
    "totalSinImpuestos": 2500000.00,
    "totalBaseImponible": 2500000.00,
    "totalImpuestos": 475000.00,
    "totalDescuentos": 0.00,
    "totalCargos": 0.00,
    "totalPagar": 2975000.00,
    "moneda": "COP"
  },

  "pago": {
    "formaPago": "2",
    "medioPago": "47",
    "fechaVencimiento": "2026-04-02"
  },

  "resolucion": {
    "numero": "18764050289527",
    "fechaInicio": "2024-01-01",
    "fechaFin": "2026-12-31",
    "prefijo": "FACT",
    "rangoInicio": 1,
    "rangoFin": 99999
  },

  "observaciones": "Factura por servicios de consultoría - Marzo 2026"
}

Response 201

json
{
  "mensaje": "Factura procesada correctamente",
  "documento": {
    "id": "507f1f77bcf86cd799439022",
    "numero": "FACT1001",
    "tipo": "01",
    "cufe": "a3d4e5f6...",
    "qrCode": "https://catalogo-vpfe.dian.gov.co/document/...",
    "fechaProcesamiento": "2026-03-02T15:30:00.000Z"
  }
}

Campos de la factura

tipoopcionalstring
Tipo de factura: "01" (venta, default), "02" (exportación), "03" o "04" (contingencia).
prefijorequeridostring
Prefijo de la resolución de numeración. Ej: "FACT".
numerorequeridonumber
Consecutivo de la factura.
fechaEmisionrequeridostring
Formato YYYY-MM-DD.
horaEmisionrequeridostring
Formato HH:MM:SS±HH:MM. Incluya zona horaria (-05:00 para Colombia).
adquirenterequeridoobject
Datos del comprador/adquirente (ver estructura Participante abajo).
lineasrequeridoarray
Al menos una línea de detalle con productos/servicios.
impuestosrequeridoarray
Totalización de impuestos a nivel de documento.
totalesrequeridoobject
Totales monetarios del documento.
pagorequeridoobject
Forma y medio de pago. Campos: formaPago ("1"=Contado, "2"=Crédito), medioPago (código DIAN), fechaVencimiento (formato YYYY-MM-DD, obligatorio cuando formaPago="2").
resolucionrequeridoobject
Datos de la resolución DIAN de numeración.
enviarEmailopcionalboolean
Si es true, envía automáticamente un email al adquirente con el PDF y XML en ZIP tras la aceptación DIAN. El email se toma del campo adquirente.email o adquirente.contacto.email. Requiere SMTP configurado en la empresa.
observacionesopcionalstring
Notas u observaciones libres.
periodoFacturacionopcionalobject
{ "inicio": "YYYY-MM-DD", "fin": "YYYY-MM-DD" }

Estructura del Participante (adquirente)

tipoOrganizacionrequeridostring
"1" = Persona jurídica, "2" = Persona natural.
tipoIdentificacionrequeridostring
Código DIAN. Ver tabla en Códigos de referencia.
numeroIdentificacionrequeridostring
Número de identificación fiscal.
razonSocialrequeridostring
Razón social o nombre completo.
responsabilidadesFiscalesrequeridostring[]
Lista de responsabilidades fiscales.
codigoTributorequeridostring
Régimen tributario del participante (diferente al código de impuesto de los productos). Valores más comunes: "01" = Responsable de IVA, "04" = Responsable de INC, "ZZ" = No responsable / No aplica. Ver Código de tributo del emisor y adquiriente.
direccionrequeridoobject
Dirección fiscal con código de municipio, departamento y país.
emailopcionalstring
Email del adquirente. Se usa para el envío automático del documento cuando enviarEmail: true.
contactoopcionalobject
{ "telefono", "email", "nombre" }
digitoVerificacionopcionalstring
DV para NIT.

Estructura de una Línea

numerorequeridonumber
Número consecutivo de la línea (empezando en 1).
descripcionrequeridostring
Descripción del producto o servicio.
cantidadrequeridonumber
Cantidad.
unidadMedidaopcionalstring
Código UNECE. Default: "94" (unidad). Otros: "KGM" (kg), "LTR" (litro), "MTR" (metro).
valorUnitariorequeridonumber
Precio unitario sin impuestos. Con 2 decimales (ej: 500000.00).
valorTotalrequeridonumber
Valor total de la línea = cantidad × valorUnitario. Con 2 decimales.
impuestosrequeridoarray
Al menos un impuesto por línea: { codigo, porcentaje, baseImponible, valor }. Todos los valores con 2 decimales.
descuentosopcionalarray
Descuentos aplicados a la línea.

Notas Crédito

Las notas crédito (tipo 91) ajustan facturas a favor del comprador. Requieren referencia al documento original y un concepto de corrección.

POST/api/v1/documentos/notas-credito

Campos adicionales respecto a la factura

conceptoCorreccionrequeridostring
Motivo de la nota crédito (ver tabla abajo).
documentoReferenciarequeridoobject
Referencia a la factura original.
resolucionopcionalobject
La resolución es opcional para notas crédito.

Conceptos de corrección — Nota Crédito

CódigoConcepto
1Devolución parcial de los bienes o no aceptación parcial del servicio
2Anulación de factura electrónica
3Rebaja o descuento parcial o total
4Ajuste de precio
5Otros

Ejemplo

json
{
  "tipo": "91",
  "prefijo": "NC",
  "numero": 1,
  "fechaEmision": "2026-03-05",
  "horaEmision": "14:00:00-05:00",
  "moneda": "COP",

  "conceptoCorreccion": "3",
  "documentoReferencia": {
    "numero": "FACT1001",
    "cufe": "a3d4e5f6...",
    "fechaEmision": "2026-03-02",
    "tipoDocumento": "01"
  },

  "adquirente": { /* ... */ },
  "lineas": [ /* ... líneas que se ajustan */ ],
  "impuestos": [ /* ... */ ],
  "totales": { /* ... */ },
  "pago": { /* ... */ }
}

Response 201

json
{
  "mensaje": "Nota crédito procesada correctamente",
  "documento": {
    "id": "507f1f77bcf86cd799439033",
    "numero": "NC1",
    "tipo": "91",
    "cude": "b4c5d6e7...",
    "qrCode": "https://catalogo-vpfe.dian.gov.co/document/...",
    "fechaProcesamiento": "2026-03-05T19:00:00.000Z"
  }
}

Notas Débito

Las notas débito (tipo 92) ajustan facturas a favor del vendedor. Misma estructura que la nota crédito pero con conceptos de corrección diferentes.

POST/api/v1/documentos/notas-debito

Conceptos de corrección — Nota Débito

CódigoConcepto
1Intereses
2Gastos por cobro
3Cambio del valor
4Otros

Ejemplo

json
{
  "tipo": "92",
  "prefijo": "ND",
  "numero": 1,
  "fechaEmision": "2026-03-10",
  "horaEmision": "09:00:00-05:00",
  "moneda": "COP",

  "conceptoCorreccion": "1",
  "documentoReferencia": {
    "numero": "FACT1001",
    "cufe": "a3d4e5f6...",
    "fechaEmision": "2026-03-02",
    "tipoDocumento": "01"
  },

  "adquirente": { /* ... */ },
  "lineas": [
    {
      "numero": 1,
      "descripcion": "Intereses por mora - 30 días",
      "cantidad": 1,
      "unidadMedida": "94",
      "valorUnitario": 50000.00,
      "valorTotal": 50000.00,
      "impuestos": [
        {
          "codigo": "01",
          "porcentaje": 19,
          "baseImponible": 50000.00,
          "valor": 9500.00
        }
      ]
    }
  ],
  "impuestos": [{ "codigo": "01", "nombre": "IVA", "porcentaje": 19, "baseImponible": 50000.00, "valor": 9500.00 }],
  "totales": {
    "totalSinImpuestos": 50000.00,
    "totalBaseImponible": 50000.00,
    "totalImpuestos": 9500.00,
    "totalDescuentos": 0.00,
    "totalCargos": 0.00,
    "totalPagar": 59500.00,
    "moneda": "COP"
  },
  "pago": { "formaPago": "1", "medioPago": "10" }
}

Factura tipo Mandato

La factura tipo Mandato (tipoOperacion=11, CustomizationID=11) se usa cuando un mandatario emite facturas a nombre de un mandante (tercero). Cada línea debe indicar si el ingreso es propio (tipoIngreso="0") o de un tercero (tipoIngreso="1"), según la tabla DIAN 13.3.13.

POST/api/v1/facturas
Campos obligatorios para mandato
tipoOperacion: "11" a nivel de documento
tipoIngreso en cada línea (DIAN tabla 13.3.13): "0" = B/S ingreso propio, "1" = B/S ingresos recibidos para terceros
mandante solo obligatorio cuando tipoIngreso="1" (tercero). Para tipoIngreso="0" (propio) se omite — el sistema lo completa automáticamente con los datos de la empresa emisora

Ejemplo — Factura Mandato

{
  "tipo": "01",
  "tipoOperacion": "11",
  "prefijo": "SETT",
  "numero": 100,
  "fechaEmision": "2026-03-02",
  "horaEmision": "10:00:00-05:00",
  "moneda": "COP",
  "enviarEmail": true,
  "adquirente": { /* adquirente — datos iguales que factura estándar (incluir "email" para envío automático) */ },
  "lineas": [
    {
      "numero": 1,
      "descripcion": "Servicio de consultoría (ingreso propio)",
      "cantidad": 1,
      "unidadMedida": "94",
      "valorUnitario": 500000.00,
      "valorTotal": 500000.00,
      "tipoIngreso": "0",
      /* mandante omitido — el sistema lo completa con los datos de la empresa */
      "impuestos": [{ "codigo": "01", "porcentaje": 19, "baseImponible": 500000.00, "valor": 95000.00 }]
    },
    {
      "numero": 2,
      "descripcion": "Venta de producto (ingreso de tercero)",
      "cantidad": 2,
      "unidadMedida": "94",
      "valorUnitario": 250000.00,
      "valorTotal": 500000.00,
      "tipoIngreso": "1",
      "mandante": {
        "tipoIdentificacion": "31",
        "numeroIdentificacion": "900555666",
        "digitoVerificacion": "1"
      },
      "impuestos": [{ "codigo": "01", "porcentaje": 19, "baseImponible": 500000.00, "valor": 95000.00 }]
    }
  ],
  "impuestos": [{ "codigo": "01", "nombre": "IVA", "porcentaje": 19, "baseImponible": 1000000.00, "valor": 190000.00 }],
  "totales": { "totalSinImpuestos": 1000000.00, "totalBaseImponible": 1000000.00, "totalImpuestos": 190000.00, "totalDescuentos": 0.00, "totalCargos": 0.00, "totalPagar": 1190000.00 },
  "pago": { "formaPago": "1", "medioPago": "10" },
  "resolucion": { "numero": "18760000001", "fechaInicio": "2024-01-19", "fechaFin": "2026-01-19", "prefijo": "SETT", "rangoInicio": 1, "rangoFin": 5000 }
}
CampoTipoDescripción
tipoOperacionstring"11" — activa modo mandato (CustomizationID=11)
enviarEmailbooleanSi es true, envía email con PDF+XML al adquirente tras aceptación DIAN
lineas[].tipoIngresostringDIAN tabla 13.3.13: "0" = B/S ingreso propio (mandante auto-inyectado desde la empresa), "1" = B/S ingresos recibidos para terceros (mandante obligatorio)
lineas[].mandante.tipoIdentificacionstringTipo de documento del mandante — solo para tipoIngreso="1" (ej: "31" para NIT)
lineas[].mandante.numeroIdentificacionstringNúmero de documento del mandante — solo para tipoIngreso="1"
lineas[].mandante.digitoVerificacionstringDígito de verificación (opcional)

Documento Soporte

El documento soporte (tipo 05) se usa para adquisiciones a proveedores no obligados a facturar. Genera un código CUDS en lugar de CUFE y usa CustomizationID=10 y tributo ZZ.

POST/api/v1/documentos/documentos-soporte
Diferencias clave
El documento soporte tiene estructura similar a la factura pero:
• El adquirente es quien emite el documento (usted)
• El emisor es el proveedor no obligado a facturar
• Use codigoTributo: "ZZ" (No aplica) para el proveedor
• El código único generado es CUDS (no CUFE)

Ejemplo

json
{
  "tipo": "05",
  "prefijo": "DS",
  "numero": 1,
  "fechaEmision": "2026-03-02",
  "horaEmision": "11:00:00-05:00",
  "moneda": "COP",
  "tipoOperacion": "10",

  "emisor": {
    "tipoOrganizacion": "2",
    "tipoIdentificacion": "13",
    "numeroIdentificacion": "1234567890",
    "razonSocial": "Pedro Proveedor",
    "responsabilidadesFiscales": ["R-99-PN"],
    "codigoTributo": "ZZ",
    "direccion": {
      "codigoMunicipio": "11001",
      "nombreCiudad": "Bogotá",
      "codigoDepartamento": "11",
      "nombreDepartamento": "Cundinamarca",
      "codigoPais": "CO",
      "nombrePais": "Colombia",
      "direccionLinea": "Carrera 10 # 5-30"
    }
  },

  "adquirente": { /* Su empresa — el que emite el doc soporte */ },
  "lineas": [ /* ... */ ],
  "impuestos": [ /* ... */ ],
  "totales": { /* ... */ },
  "pago": { /* ... */ },
  "resolucion": { /* resolución para doc soporte */ }
}

Notas de Ajuste

Las notas de ajuste (tipo 95) corrigen documentos soporte. Son equivalentes a las notas crédito pero para documentos soporte (tipo 05). Generan CUDS y usan CustomizationID=10.

POST/api/v1/documentos/notas-ajuste

Conceptos de corrección — Nota de Ajuste

CódigoConcepto
1Devolución parcial de los bienes o no aceptación parcial del servicio
2Anulación del documento soporte
3Rebaja o descuento parcial o total
4Ajuste de precio
5Otros

Ejemplo

json
{
  "tipo": "95",
  "prefijo": "NA",
  "numero": 1,
  "fechaEmision": "2026-03-10",
  "horaEmision": "15:00:00-05:00",
  "moneda": "COP",

  "conceptoCorreccion": "2",
  "documentoReferencia": {
    "numero": "DS1",
    "cufe": "c5d6e7f8...",
    "fechaEmision": "2026-03-02",
    "tipoDocumento": "05"
  },

  "adquirente": { /* ... */ },
  "lineas": [ /* ... */ ],
  "impuestos": [ /* ... */ ],
  "totales": { /* ... */ },
  "pago": { /* ... */ }
}

Consultas

Endpoints para listar, consultar estado, descargar XML/PDF y más.

Listar documentos

GET/api/v1/documentos

Parámetros de consulta

tipoopcionalstring
Filtrar por tipo: "01", "91", "92", "05", "95".
fechaDesdeopcionalstring
Fecha inicio (YYYY-MM-DD).
fechaHastaopcionalstring
Fecha fin (YYYY-MM-DD).
paginaopcionalnumber
Número de página (paginación).
porPaginaopcionalnumber
Cantidad de resultados por página.
bash
curl -G https://su-dominio.com/api/v1/documentos \
  -H "Authorization: Bearer TOKEN" \
  --data-urlencode "tipo=01" \
  --data-urlencode "fechaDesde=2026-03-01" \
  --data-urlencode "fechaHasta=2026-03-31" \
  --data-urlencode "pagina=1" \
  --data-urlencode "porPagina=20"

Obtener un documento

GET/api/v1/documentos/:id

Consultar estado en DIAN

GET/api/v1/documentos/:id/estado

Consulta el estado del documento directamente en la DIAN vía SOAP.

Response

json
{
  "estado": {
    "codigo": "00",
    "descripcion": "Procesado Correctamente",
    "esValido": true,
    "fechaRespuesta": "2026-03-02T16:00:00.000Z"
  }
}

Descargar XML

GET/api/v1/documentos/:id/xml

Retorna el XML firmado con Content-Type application/xml.

bash
curl https://su-dominio.com/api/v1/documentos/DOCUMENTO_ID/xml \
  -H "Authorization: Bearer TOKEN" \
  -o factura.xml

Descargar PDF

GET/api/v1/documentos/:id/pdf

Retorna la representación gráfica en PDF.

bash
curl https://su-dominio.com/api/v1/documentos/DOCUMENTO_ID/pdf \
  -H "Authorization: Bearer TOKEN" \
  -o factura.pdf

Enviar por email

POST/api/v1/documentos/:id/enviar-email
json
{
  "email": "cliente@empresa.com"
}

Consultar adquirente en DIAN

GET/api/v1/documentos/consultar-adquirente
bash
curl -G https://su-dominio.com/api/v1/documentos/consultar-adquirente \
  -H "Authorization: Bearer TOKEN" \
  --data-urlencode "tipoDocumento=31" \
  --data-urlencode "numeroDocumento=900123456"

Envío a DIAN

Una vez creado el documento, puede enviarlo a la DIAN para su validación. El sistema empaqueta el XML firmado en formato ZIP y lo envía mediante SOAP.

Enviar a producción

POST/api/v1/documentos/:id/enviar

Envía el documento al ambiente de producción de la DIAN.

bash
curl -X POST https://su-dominio.com/api/v1/documentos/DOCUMENTO_ID/enviar \
  -H "Authorization: Bearer TOKEN"

Enviar al test set (habilitación)

POST/api/v1/documentos/:id/enviar-test-set

Envía el documento al test set de habilitación de la DIAN.

Verificar estado del servicio DIAN

GET/api/v1/dian/estado

No requiere autenticación. Verifica la disponibilidad de los servicios web de la DIAN.

json
{
  "servicio": "DIAN Web Services",
  "fechaConsulta": "2026-03-02T16:00:00.000Z",
  "ambientes": {
    "habilitacion": {
      "url": "https://habilitacionws.dian.gov.co/...",
      "disponible": true,
      "tiempoMs": 342
    },
    "produccion": {
      "url": "https://ws.dian.gov.co/...",
      "disponible": true,
      "tiempoMs": 421
    }
  }
}

Habilitación DIAN

Para emitir documentos electrónicos en producción, su empresa debe completar el proceso de habilitación ante la DIAN. Este sistema automatiza gran parte del proceso.

Proceso de habilitación

  1. Configure la empresa con dianAmbiente: 2 (habilitación), su dianSoftwareId, dianSoftwarePin y dianTestSetId.
  2. Suba el certificado digital (.p12) usando el endpoint de certificado.
  3. Genere la factura de habilitación usando el endpoint dedicado. Se envía automáticamente al test set.
  4. Consulte el estado del test set hasta que la DIAN acepte el documento. Al ser aceptado, el ambiente cambia automáticamente a producción.

Generar factura de habilitación

POST/api/v1/empresas/:id/factura-habilitacion

Genera una factura de prueba con datos de ejemplo y la envía al test set DIAN automáticamente.

bash
curl -X POST https://su-dominio.com/api/v1/empresas/EMPRESA_ID/factura-habilitacion \
  -H "Authorization: Bearer TOKEN"

Response 201

json
{
  "mensaje": "Factura de habilitación generada y enviada al test set DIAN",
  "documento": {
    "id": "507f1f77bcf86cd799439044",
    "numero": "SETP990000001",
    "tipo": "01",
    "cufe": "d6e7f8a9..."
  },
  "testSet": { /* respuesta del test set DIAN */ }
}

Consultar estado del test set

GET/api/v1/documentos/:id/estado-test-set
Auto-habilitación
Cuando la DIAN acepta el documento de prueba, el sistema cambia automáticamente dianAmbiente de 2 (habilitación) a 1 (producción). No necesita hacer nada más.

Response (habilitado)

json
{
  "resultado": {
    "statusCode": "00",
    "statusDescription": "Procesado Correctamente",
    "esAceptado": true,
    "empresaHabilitada": true
  },
  "mensaje": "La empresa ha sido habilitada automáticamente. El ambiente se cambió a producción (1)."
}

Catálogos DIAN

Las tablas de referencia DIAN (tributos, tipos de identificación, municipios, medios de pago, etc.) están disponibles como endpoints públicos. No requieren autenticación.

Endpoint público
Estos endpoints no requieren autenticación ni token JWT. Son útiles para llenar dropdowns en su interfaz o validar códigos antes de enviar documentos.

Listar tipos de catálogos

GET/api/v1/catalogos

Retorna los tipos de catálogos disponibles: tributo, tipoIdentificacion, responsabilidadFiscal, medioPago, departamento, municipio, unidadMedida, moneda, pais, tarifaImpuesto.

Obtener items de un catálogo

GET/api/v1/catalogos/:tipo

Retorna todos los items activos del catálogo especificado.

Ejemplos

bash
# Todos los tributos
curl https://tu-dominio.com/api/v1/catalogos/tributo

# Municipios de Bogotá D.C.
curl https://tu-dominio.com/api/v1/catalogos/municipio?departamento=11

# Municipios de Antioquia
curl https://tu-dominio.com/api/v1/catalogos/municipio?departamento=05

# Tarifas de IVA
curl https://tu-dominio.com/api/v1/catalogos/tarifaImpuesto?tributo=01

# Tarifas de ReteRenta
curl https://tu-dominio.com/api/v1/catalogos/tarifaImpuesto?tributo=06

# Tipos de identificación
curl https://tu-dominio.com/api/v1/catalogos/tipoIdentificacion

# Medios de pago (76 códigos)
curl https://tu-dominio.com/api/v1/catalogos/medioPago

# Unidades de medida
curl https://tu-dominio.com/api/v1/catalogos/unidadMedida

Respuesta

json
{
  "tipo": "tributo",
  "total": 23,
  "items": [
    {
      "tipo": "tributo",
      "codigo": "01",
      "nombre": "IVA",
      "descripcion": "Impuesto al Valor Agregado",
      "activo": true,
      "metadata": { "tarifas": [0, 5, 19] }
    }
  ]
}

Validación automática

Los siguientes campos se validan automáticamente contra los catálogos DIAN al enviar documentos:

CampoCatálogoEjemplo válido
tipoIdentificaciontipoIdentificacion (13 códigos)"31" (NIT)
codigoTributotributo (23 códigos)"01" (IVA)
responsabilidadesFiscales[]responsabilidadFiscal (5 códigos)"O-15"
medioPagomedioPago (76 códigos)"10" (Efectivo)
impuestos[].codigotributo (23 códigos)"01" (IVA)
Códigos no válidos
Si envía un código que no existe en el catálogo DIAN, recibirá un error 400 con un mensaje indicando qué tabla de referencia consultar. Use los endpoints de catálogos para verificar los códigos válidos antes de enviar documentos.

Rate limiting

Los endpoints de catálogos tienen un límite de 200 peticiones cada 15 minutos por IP.

Códigos de Referencia DIAN

Tablas de referencia rápida para los códigos más utilizados. Para la lista completa, use el endpoint GET /api/v1/catalogos/:tipo.

Tipos de identificación

CódigoDescripción
11Registro civil de nacimiento
12Tarjeta de identidad
13Cédula de ciudadanía
21Tarjeta de extranjería
22Cédula de extranjería
31NIT
41Pasaporte
42Documento de identificación extranjero
47PEP (Permiso Especial de Permanencia)
48PPT (Permiso por Protección Temporal)
50NIT de otro país
91NUIP
00No obligado a registrarse en el RUT

Códigos de tributos

CódigoNombreDescripción
01IVAImpuesto al Valor Agregado
02ICImpuesto al Consumo
03ICAImpuesto de Industria y Comercio
04INCImpuesto Nacional al Consumo
05ReteIVARetención en la fuente por IVA
06ReteRentaRetención en la fuente a título de renta
07ReteICARetención en la fuente por ICA
08IC PorcentualImpuesto al Consumo porcentual
20FtoHorticulturaCuota de fomento hortifrutícola
21TimbreImpuesto de timbre
22INC BolsasINC bolsas plásticas
23INComINC comestibles
24AdValoremImpuesto Ad Valorem
25Contribución NominalContribución nominal sobre transacciones
26IBUAImpuesto a Bebidas Ultraprocesadas Azucaradas
27ICUIImpuesto a Comestibles Ultraprocesados Industrialmente
30IC DatosImpuesto al Consumo de Datos
32IC VehículosImpuesto al Consumo de Vehículos
33IC TelecomunicacionesImpuesto al Consumo de Telecomunicaciones
34IC Act. FinancieraImpuesto al Consumo Actividad Financiera
35Sobretasa CombustiblesSobretasa a los combustibles
36Contribución CombustiblesContribución sobre combustibles
ZZNo aplicaUsado en documentos soporte (no obligados)

Código de tributo del emisor y adquiriente

El campo codigoTributo dentro del objeto emisor y adquiriente indica el régimen tributario al que pertenece cada participante. Este campo es diferente al código de tributo de los impuestos del documento (impuestos[].codigo), que identifica el tipo de impuesto aplicado a los productos o servicios.

Tipo de participanteCódigoEjemplo
Responsable de IVA (régimen común)01Sociedad SAS, empresa régimen común
Responsable de INC (Impuesto Nacional al Consumo)04Restaurantes, bares, telecomunicaciones
No responsable de IVA / Sin detalle tributarioZZConsumidor final, persona natural no responsable
Persona jurídica sin régimen tributario específicoZZEntidades sin ánimo de lucro
Proveedor no obligado (Documento Soporte tipo 05)ZZCampesino, vendedor informal
Regla general
Si el participante es responsable de IVA use "01". Si no es responsable o no tiene detalle tributario, use "ZZ". En caso de duda, consulte el RUT del participante donde aparece su responsabilidad fiscal.

Formas de pago

CódigoDescripción
1Contado
2Crédito

Medios de pago

CódigoDescripción
1No definido
2Crédito ACH
3Débito ACH
10Efectivo
20Cheque
42Consignación bancaria
47Transferencia bancaria
48Tarjeta crédito
49Tarjeta débito
ZZZMutuo acuerdo

Responsabilidades fiscales comunes

CódigoDescripción
O-13Gran contribuyente
O-15Autorretenedor
O-23Agente de retención IVA
O-47Régimen simple de tributación
R-99-PNNo aplica — Otros

Errores Comunes

Guía de resolución para los errores más frecuentes.

Errores HTTP

CódigoSignificadoSolución
400Datos inválidosRevise el body del request. La respuesta incluye detalles del error de validación.
401No autenticadoToken faltante, expirado o inválido. Realice login nuevamente.
403Sin permisosSu rol no tiene acceso a este recurso. Contacte al administrador.
404No encontradoEl recurso no existe o no pertenece a su empresa.
429Rate limitDemasiadas peticiones. Espere y reintente. Límite general: 100 req/15min, documentos: 30 req/15min, catálogos: 200 req/15min.
500Error internoError del servidor. Si persiste, contacte soporte con el ID de la petición.

Errores de validación DIAN

Cuando el documento no pasa las validaciones DIAN, la respuesta incluye los errores detallados:

json
{
  "error": "El documento no pasó las validaciones DIAN",
  "errores": [
    {
      "codigo": "FAD06",
      "mensaje": "Valor del tributo no corresponde al porcentaje aplicado",
      "tipo": "rechazo"
    }
  ],
  "advertencias": [
    "El código postal no está registrado en la tabla de la DIAN"
  ]
}

Errores de validación de catálogos

El sistema valida automáticamente que los códigos enviados existan en los catálogos DIAN:

json
{
  "error": "Error de validación",
  "detalles": [
    {
      "campo": "adquirente.tipoIdentificacion",
      "mensaje": "Tipo de identificación no válido según catálogo DIAN (Tabla 13.2.1)"
    }
  ]
}

Campos validados: tipoIdentificacion, codigoTributo, responsabilidadesFiscales, medioPago, y impuestos[].codigo. Consulte GET /api/v1/catalogos/:tipo para ver los códigos válidos.

Problemas frecuentes y soluciones

Los impuestos no cuadran

Error típico
El total de impuestos a nivel de documento debe ser la suma exacta de los impuestos de cada línea. Verifique que:
• Cada lineas[].impuestos[].valor = baseImponible × porcentaje / 100 con 2 decimales
impuestos[].valor a nivel de documento = sumatoria exacta de lineas[].impuestos[].valor del mismo código de tributo
impuestos[].baseImponible a nivel de documento = sumatoria de lineas[].impuestos[].baseImponible del mismo código

Ejemplo: Si tiene 3 líneas con IVA de 190000.00, 285000.00 y 0.00, el impuesto totalizado debe ser exactamente 475000.00, no 475000.

Certificado digital rechazado

  • Verifique que el archivo sea formato .p12 o .pfx
  • Verifique que la contraseña sea correcta
  • Verifique que el certificado no haya expirado
  • El certificado debe ser de una CA reconocida por la DIAN

Error de conexión con DIAN

  • Verifique el estado del servicio con GET /api/v1/dian/estado
  • La DIAN tiene ventanas de mantenimiento frecuentes (especialmente fines de semana)
  • Si el ambiente es 2 (habilitación), use los servicios de habilitación, no producción

Documento rechazado por la DIAN

  • Consulte el estado con GET /api/v1/documentos/:id/estado para ver los errores específicos
  • Los errores de tipo "rechazo" requieren corregir y reenviar
  • Los errores de tipo "notificacion" son advertencias que no impiden la aceptación

Rate limiting

Límites
General: 100 peticiones cada 15 minutos.
Creación de documentos: 30 peticiones (POST) cada 15 minutos.
Catálogos: 200 peticiones cada 15 minutos.
Login: 5 intentos cada 15 minutos por IP.
Si excede el límite, recibirá un error 429. Espere el tiempo indicado antes de reintentar.