Manual de integración

API de extracción de documentos electrónicos DIAN

Cómo consultar de forma masiva las facturas de compra y de venta registradas en el catálogo de la DIAN, y descargar sus XML desde su propio sistema.

Versión 1.0 Protocolo REST · JSON Ambiente Producción
01

Qué hace este servicio

El servicio consulta el catálogo de la DIAN y devuelve los documentos electrónicos de un rango de fechas, con toda su información estructurada y, si se solicita, el XML original firmado de cada documento.

Se resuelve en dos etapas, que la API encadena automáticamente:

  1. Listado. Obtiene del catálogo los CUFE de todos los documentos del rango, con su emisor, folio, fecha, estado y valor.
  2. Consulta. Por cada CUFE pregunta a la DIAN, firmando con el certificado digital, y devuelve el XML original del documento.
Importante

La información proviene directamente de la DIAN en cada consulta. El servicio no mantiene una copia de los documentos: actúa como pasarela, no como repositorio. Vea la sección Almacenamiento.

02

Antes de empezar

Para consumir la API necesita tener a mano lo siguiente:

ElementoPara qué sirveQuién lo entrega
URL baseDirección del servicioÁgil Factura
API Key
X-Api-Key
Autenticar los endpoints de listado y de XML por CUFEÁgil Factura
Token de empresa
Authorization: Bearer
Autenticar el flujo completo usando el certificado ya configuradoÁgil Factura
Enlace AuthToken de la DIANAutorizar la consulta del catálogo. Cambia en cada extracciónLa DIAN, por correo
Certificado .p12 y su contraseñaSolo si usará el endpoint de XML por CUFE enviando el certificadoSu entidad certificadora
Seguridad

La API Key y el token de empresa son credenciales: consúmalas desde su servidor, nunca desde el navegador ni desde una aplicación móvil, y no las publique en repositorios. Si sospecha que se expusieron, solicite su rotación.

03

El token de la DIAN

Es el punto que más dudas genera, así que conviene entenderlo bien. La DIAN envía por correo un enlace de autorización con esta forma:

https://catalogo-vpfe.dian.gov.co/User/AuthToken?pk=10910094|53031455&rk=901234567&token=6b84e2c2-9530-4e02-8bc0-647da438d804

Ese enlace completo es lo que se envía en el campo url de cada petición.

Tres reglas que debe respetar

ReglaDetalle
CaducaTiene vigencia limitada. Genere uno nuevo justo antes de cada extracción; no lo guarde para reutilizarlo al día siguiente.
Debe ser del mismo ambienteUn token de habilitación no sirve para consultar documentos de producción, y viceversa.
Va completoCópielo íntegro, incluidos pk, rk y token. Si recorta algún parámetro, la consulta falla.
Sobre el carácter «|»

El enlace de la DIAN contiene una barra vertical en el parámetro pk, que no es un carácter válido en una URL. El servicio la codifica automáticamente, así que puede pegar el enlace tal como lo recibió. Si su cliente HTTP valida URLs por su cuenta, envíela como %7C.

04

Autenticación

Hay dos formas, según el endpoint que use.

A · API Key para volumen

X-Api-Key: <api_key>

Es la que usan los dos endpoints del flujo principal. Una sola clave sirve para todas las empresas que usted maneje: el certificado de cada una viaja dentro de la petición, así que no hay nada que registrar previamente.

Como el certificado va en el cuerpo, use siempre HTTPS y consuma la API desde su servidor, nunca desde el navegador.

B · Token de empresa

Authorization: Bearer <token_de_empresa>

Alternativa para los endpoints de extracción completa. El servicio firma con el certificado que la empresa ya tiene configurado, de modo que usted no lo envía — pero requiere dar de alta cada empresa con su certificado, lo que no resulta práctico cuando son muchas.

05

Compras y ventas

El campo tipo determina qué documentos se extraen:

ValorQué traeConsideraciones
Received Compras — documentos que le emitieron a su empresa Se valida que su empresa sea el adquiriente. Son los únicos sobre los que pueden registrarse eventos RADIAN.
Sent Ventas — documentos que su empresa emitió Solo para consulta y reportes. No aplican eventos RADIAN.

Para obtener ambos debe hacer dos extracciones separadas, una por cada valor. El resto de los parámetros es idéntico.

Tipos de documento

El listado incluye todo lo que la DIAN registre en el rango: facturas electrónicas, notas crédito y débito, documentos equivalentes POS y títulos valor. Filtre por el campo tipoDoc si solo le interesan algunos.

06

Endpoints

Los dos que necesita

Para extraer XML de forma masiva bastan los dos primeros. Ambos usan la misma API Key y no requieren registrar ninguna empresa en el servicio. Los demás son alternativas para casos puntuales.

POST /api/cufes X-Api-Key

Devuelve únicamente el listado del catálogo, sin consultar cada documento. Es mucho más rápido y sirve para saber qué hay antes de decidir qué extraer.

{
  "success": true,
  "total":   6,
  "data": [{
    "cufe":          "1ac814c2df59984f...",
    "tipoDoc":       "01",
    "folio":         "DPOS73771",
    "fechaEmision":  "26-07-2026",
    "nitEmisor":     "901772356",
    "nombreEmisor":  "GRUPO RC S.A.S.",
    "estado":        "Aprobado",
    "EstadoRadian":  "No Aplica",
    "valor":         "$ 246.850"
  }]
}
POST /api/ubl2.1/xml/by-cufes X-Api-Key

Entrega el XML original firmado de una lista de CUFE, en base64. Hasta 500 documentos por llamada. No requiere que su empresa esté registrada en el servicio: el certificado viaja en la petición.

{
  "certificate": "<contenido del .p12 en base64>",
  "password":    "<contraseña del certificado>",
  "ambiente":    1,                 // 1 producción · 2 habilitación
  "cufes":       [ "1669c097...", "18a20b3d..." ]
}
{
  "success": true, "total": 2, "ok": 2,
  "data": [{
    "cufe":      "1669c097...",
    "success":   true,
    "xmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIi..."
  }]
}

Alternativas

Estas tres usan token de empresa, lo que exige que cada empresa esté registrada en el servicio con su certificado. Sirven cuando se opera una sola empresa, no cuando son muchas.

POST /api/extractor/company Bearer

Inicia una extracción completa. Responde de inmediato con un identificador de trabajo, sin esperar a que termine el proceso. Es el endpoint principal.

{
  "tipo":       "Received",
  "fechaDesde": "2026-07-01",
  "fechaHasta": "2026-07-31",
  "url":        "https://catalogo-vpfe.dian.gov.co/User/AuthToken?..."
}
{
  "success":   true,
  "jobId":     "19e1f865-8d68-4b93-8f1a-b162eb27ca08",
  "statusUrl": "https://.../api/extractor/company/jobs/19e1f865-..."
}
GET /api/extractor/company/jobs/{jobId} Bearer

Consulta el avance y, al finalizar, entrega el resultado. Repita la llamada cada 15–20 segundos hasta que status sea done.

{
  "status":    "running",      // running · done · error
  "stage":     "enriching",
  "total":     6,
  "processed": 5,
  "log":       [ "..." ],
  "data":      [ /* documentos, al terminar */ ]
}
POST /api/extractor/company/stream Bearer

Hace todo el proceso en una sola llamada y responde al terminar. no recomendado

Mantiene la conexión abierta durante todo el proceso, por lo que el servidor web la corta con un error 504 en cuanto hay unos pocos documentos. Úselo solo para pruebas rápidas con rangos mínimos; para todo lo demás use el flujo asíncrono.

07

El XML que recibe

El campo xmlBase64 contiene el documento UBL 2.1 firmado, tal como lo tiene la DIAN. No es un extracto ni una conversión: es el archivo original, con validez legal, que usted procesa y conserva.

Qué trae

  • La firma digital XAdES del emisor y la validación de la DIAN.
  • Las extensiones DIAN (sts:DianExtensions) con el CUFE, la resolución de numeración y el rango autorizado.
  • Emisor y adquiriente completos, con identificación, régimen y ubicación.
  • Totales, desglose de impuestos, retenciones y el detalle de todos los renglones.
  • Notas, medios de pago, descuentos y cargos.

Cómo obtenerlo

Decodifique el base64 y guarde el resultado como archivo .xml:

# PHP
file_put_contents("$cufe.xml", base64_decode($doc['xmlBase64']));

# Python
open(f"{cufe}.xml", "wb").write(base64.b64decode(doc["xmlBase64"]))

El contenido decodificado empieza siempre por <?xml version="1.0"...><Invoice ...> (o CreditNote / DebitNote según el tipo de documento).

Nota

Junto al XML, la respuesta incluye algunos campos ya extraídos (CUFE, emisor, totales) que sirven para identificar el documento sin abrirlo. Si su sistema procesa el XML directamente, puede ignorarlos.

08

Flujo recomendado

Dos llamadas por cada empresa y período. Sin trabajos asíncronos ni consultas de avance.

  1. Obtener un enlace AuthToken nuevo de la DIAN para esa empresa.
  2. POST /api/cufes con el rango de fechas → devuelve los CUFEs del período.
  3. POST /api/ubl2.1/xml/by-cufes con esos CUFEs y el certificado → devuelve los XML.
  4. Decodificar cada xmlBase64, guardarlo y causarlo en su sistema.
  5. Repetir con tipo: "Sent" si también necesita las ventas.
# 1 · listar
curl -X POST https://<url-base>/api/cufes \
  -H "X-Api-Key: <api_key>" -H "Content-Type: application/json" \
  -d '{"tipo":"Received","fechaDesde":"2026-07-01","fechaHasta":"2026-07-31","url":"<authtoken>"}'

# 2 · traer los XML (en lotes)
curl -X POST https://<url-base>/api/ubl2.1/xml/by-cufes \
  -H "X-Api-Key: <api_key>" -H "Content-Type: application/json" \
  -d '{"certificate":"<p12_base64>","password":"<clave>","ambiente":1,"cufes":["..."]}'

Cuando son muchas empresas

El esquema escala sin configuración adicional, y esa es su principal ventaja:

  • Una sola API Key para toda la operación, sin importar cuántas empresas maneje.
  • Los certificados se quedan de su lado. No hay que cargarlos ni registrarlos en el servicio: viajan en cada petición.
  • Lo único que cambia por empresa son sus credenciales DIAN: su enlace AuthToken y su .p12.
El punto que más trabajo cuesta

El enlace AuthToken es uno por empresa y caduca. Con muchas empresas, conseguir los enlaces vigentes es la parte más pesada del proceso — conviene planificarla antes de automatizar el resto.

09

Límites y rendimiento

AspectoLímiteQué significa
CUFEs por llamada500Tope de /api/ubl2.1/xml/by-cufes. Es el máximo que acepta, no el recomendado — vea abajo.
Llamadas totalessin topePuede paginar tantos lotes como necesite.
Rango de fechassin topeUn rango amplio simplemente tarda más en listar.

El límite real es el tiempo, no la cantidad

El servicio consulta la DIAN una vez por cada documento, de forma secuencial. Un lote de 500 CUFEs son 500 consultas encadenadas, y puede tardar más de lo que el servidor web permite mantener abierta una petición.

Tamaño de lote sugerido

Use lotes de 100 a 150 CUFEs. Para afinarlo a su servidor, envíe un lote de 10 y mida cuánto tarda: divida ese tiempo entre 10 y aplique lote = 300 s ÷ segundos_por_documento. Lotes más pequeños además son más fáciles de reintentar cuando algo falla.

Tiempos de referencia

OperaciónTiempoPor qué
Listar un período1–2 minAbre un navegador contra el portal, autentica y recorre las páginas.
Un XML por CUFE~2 sConsulta directa al servicio web, sin navegador.
Configuración del servidor

El listado suele tardar más de un minuto, así que el servidor web debe permitirlo. Con los valores por defecto (60 s) la petición se corta con un error 504. Solicite a su proveedor que los tiempos de espera estén en 600 segundos.

Recomendaciones

  • Extraiga por períodos mensuales y por empresa. Es más fácil de reintentar que un rango de un año.
  • Programe el proceso en tareas de fondo o nocturnas, nunca dentro de una petición de usuario.
  • No vuelva a pedir lo que ya tiene. Guarde por CUFE y consulte solo lo nuevo.
  • Compare ok contra total en cada respuesta y reintente solo los CUFEs que fallaron.
  • Procese los lotes en serie, no en paralelo, para no saturar el servicio ni la DIAN.
10

Almacenamiento de los XML

Punto clave

El servicio no archiva los documentos. Los consulta a la DIAN, se los entrega en la respuesta y no conserva copia. Si necesita los XML para efectos contables o de auditoría, guardarlos es responsabilidad de su sistema.

Al recibir un xmlBase64, decodifíquelo y persístalo. Una convención simple:

almacenamiento/xml/<NIT>/<AAAA-MM>/<CUFE>.xml

Guarde también el CUFE en su base de datos como identificador único del documento: le sirve para no volver a descargarlo y para cualquier consulta posterior.

Ventaja del diseño

Que el servicio no almacene nada significa que su información no queda duplicada en un tercero, y que siempre recibe el documento tal como lo tiene la DIAN en ese momento.

11

Errores

CódigoSignificadoQué hacer
401Credencial ausente o incorrectaRevise el encabezado Authorization o X-Api-Key.
422Datos inválidos, o empresa sin certificado configuradoVerifique el formato de fechas (AAAA-MM-DD) y que el enlace de la DIAN esté completo.
404Trabajo inexistente o vencidoPasaron más de 2 horas. Inicie la extracción de nuevo.
502No hay comunicación con el componente de extracciónReintente en unos minutos; si persiste, avise a Ágil Factura.
504La petición excedió el tiempo permitidoOcurre al usar /stream. Cambie al flujo asíncrono.

Errores por documento

Una extracción puede terminar correctamente y aun así tener documentos individuales con error. Revise siempre los contadores del resultado:

  • Procesados — cuántos se intentaron.
  • OK — cuántos se obtuvieron completos.
  • No coincide — el adquiriente del documento no corresponde a su NIT.
  • Error — la DIAN no devolvió el documento. Reintente esos CUFE por separado.
12

Checklist de integración

Antes de dar por terminada la integración, verifique que su sistema:

  • Solicita un enlace AuthToken nuevo por empresa en cada extracción, sin reutilizar el anterior.
  • Usa /api/cufes y /api/ubl2.1/xml/by-cufes como flujo principal.
  • Divide los CUFEs en lotes de 100 a 150, ajustados a la medición de su servidor.
  • Procesa los lotes en serie, no en paralelo.
  • Almacena los XML por su cuenta, indexados por CUFE, y no vuelve a pedir lo ya descargado.
  • Compara ok contra total y reintenta solo los CUFEs fallidos.
  • Extrae compras y ventas por separado (Received y Sent).
  • Corre en un proceso de fondo o tarea programada, no dentro de una petición de usuario.
  • Guarda las credenciales y los certificados fuera del código, y los consume solo desde el servidor.
  • Reintenta con espera progresiva cuando la DIAN no responde.
  • Confirmó con su proveedor que los tiempos de espera del servidor están en 600 segundos.