Consultar y descargar
Emitir es asíncrono: el 201 solo dice QUEUED. El número, el CUFE, el
XML y el PDF llegan después. Esta página es la otra mitad del trabajo —
cómo ver en qué quedó cada documento y cómo bajar sus archivos.
Listar documentos
Sección titulada «Listar documentos»GET/v1/documents
Devuelve los documentos de tu emisor, del más reciente al más viejo
(orden por created_at descendente). Sin filtros, trae los últimos 20.
Filtros
Sección titulada «Filtros»| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
status |
string | No | Deja solo los de ese estado. Uno de DRAFT, QUEUED, SIGNED, SENT, VALIDATED, REJECTED, CONTINGENCY, FAILED, DISCARDED. En mayúsculas y exacto: validated no vale. |
type |
string | No | Tipo DIAN: 01 factura de venta, 91 nota crédito, 92 nota débito, 05 documento soporte, 20 documento equivalente POS. |
from |
string | No | Fecha de emisión desde, YYYY-MM-DD. Inclusive. |
to |
string | No | Fecha de emisión hasta, YYYY-MM-DD. Inclusive. |
page |
entero | No | Página. Por defecto 1. Un valor menor se sube a 1. |
limit |
entero | No | Documentos por página. Por defecto 20, máximo 100. |
Los seis se validan antes de tocar la base. Un estado o un tipo que no
esté en la lista devuelve 422 diciéndote cuáles valen, y una fecha o
un número mal escritos, 422 nombrando el parámetro. Mandar la clave
vacía —?status=— es «sin filtro», no un error: es lo que manda un
selector puesto en «Todos».
Pedir limit=500 no falla: te devuelve 100. Mira pagination.pages
antes de dar por hecho que todo cupo en una llamada.
curl -G https://sandbox.facturacion.misofk.com/v1/documents \ -H "Authorization: Bearer $TOKEN" \ -d status=VALIDATED \ -d type=01 \ -d from=2026-09-01 \ -d to=2026-09-30 \ -d limit=50Respuesta
Sección titulada «Respuesta»{ "data": [ { "id": "b1f3a7d0-9c42-4e18-8a5b-6d0e2f4c9a11", "type": "01", "reference_code": "VE-2026-000841", "full_number": "SETP990000841", "prefix": "SETP", "number": "990000841", "status": "VALIDATED", "cufe": "8f2c1a9d...", "qr_url": "https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey=8f2c1a9d...", "qr_content": "NumFac: SETP990000841\nFecFac: 2026-09-04\n...", "issue_date": "2026-09-04", "issue_time": "14:22:35-05:00", "totals": { "lineExtensionAmount": "113000.00", "taxInclusiveAmount": "134470.00", "payableAmount": "134470.00", "taxTotals": { "01": { "taxableAmount": "113000.00", "taxAmount": "21470.00" } } }, "environment": "PRODUCCION", "email_sent_at": "2026-09-04T19:24:02.881Z", "email_to": "facturacion@elpoblado.com.co", "email_error": null, "created_at": "2026-09-04T14:22:31.004Z" } ], "pagination": { "page": 1, "limit": 50, "total": 143, "pages": 3 }}Cada elemento de data tiene la misma forma que la respuesta de
emisión: todos los campos del documento, incluidos items y totals
recalculados por el servidor. Lo único que no viene aquí es qr_image.
Campo de pagination |
Descripción |
|---|---|
page |
La página que se sirvió, ya normalizada. |
limit |
Los que caben por página, ya recortado a 100. |
total |
Documentos que cumplen los filtros, no los de esta página. |
pages |
total dividido entre limit, redondeado hacia arriba. |
Detalle de un documento
Sección titulada «Detalle de un documento»GET/v1/documents/:id
:id es el UUID que devolvió la emisión, no el full_number ni el
reference_code. Un id mal formado ni siquiera llega al servicio:
responde 400 con Validation failed (uuid is expected).
curl https://sandbox.facturacion.misofk.com/v1/documents/b1f3a7d0-9c42-4e18-8a5b-6d0e2f4c9a11 \ -H "Authorization: Bearer $TOKEN"Devuelve lo mismo que el listado más un campo:
| Campo | Descripción |
|---|---|
qr_image |
El QR ya dibujado, como data URI de un PNG de 300 px (data:image/png;base64,…). Listo para un <img src>. |
Errores
Sección titulada «Errores»| Código | code |
Cuándo |
|---|---|---|
400 |
VALIDATION |
El :id no es un UUID |
401 |
UNAUTHORIZED |
API key inválida o ausente |
404 |
NOT_FOUND |
Documento no encontrado — no existe, o no es de tu emisor |
El QR: qr_content, no qr_url
Sección titulada «El QR: qr_content, no qr_url»Tres formas del mismo QR, para tres necesidades distintas:
| Campo o ruta | Qué es | Para qué sirve |
|---|---|---|
qr_content |
El texto exacto que se firmó y que va dentro del código. | Dibujar el QR tú mismo. Codifícalo literal, sin reordenar ni recortar. |
qr_url |
La dirección del catálogo de la DIAN. | Imprimirla al lado del QR, para quien prefiera teclearla. |
qr_image |
PNG en data URI, en el detalle del documento. | Pegarlo en tu representación gráfica sin dibujar nada. |
GET /v1/documents/:id/qr |
El mismo PNG como archivo. | Cuando prefieres una URL a arrastrar un data URI. |
Así se ve qr_content de la factura del ejemplo. Las etiquetas, el orden
y los saltos de línea son parte del contenido:
NumFac: SETP990000841FecFac: 2026-09-04HorFac: 14:22:35-05:00NitFac: 900654321DocAdq: 901234567ValFac: 113000.00ValIva: 21470.00ValOtroIm: 0.00ValTolFac: 134470.00CUFE: 8f2c1a9d...https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey=8f2c1a9d...La URL es la última línea del bloque. Ahí está la relación entre los dos
campos: qr_url está contenido en qr_content, y por eso codificar
solo la URL parece funcionar hasta que alguien valida el documento.
qr_url apunta a catalogo-vpfe.dian.gov.co en producción y a
catalogo-vpfe-hab.dian.gov.co en habilitación. El emisor decide cuál,
con su environment.
PNG del código QR
Sección titulada «PNG del código QR»GET/v1/documents/:id/qr
No devuelve JSON: devuelve el binario.
Content-Type: image/pngContent-Length: <bytes>Cache-Control: public, max-age=31536000, immutablePNG de 300 px, nivel de corrección M. El immutable es de verdad: el
QR de un documento firmado no cambia nunca, así que puedes cachearlo sin
plazo.
| Código | code |
Mensaje |
|---|---|---|
404 |
NOT_FOUND |
El documento todavía no tiene QR: se genera al firmarlo |
404 |
NOT_FOUND |
Documento no encontrado |
Los cuatro archivos
Sección titulada «Los cuatro archivos»GET/v1/documents/:id/xml
GET/v1/documents/:id/pdf
GET/v1/documents/:id/attached-document
GET/v1/documents/:id/application-response
Los cuatro devuelven el archivo crudo, con
Content-Disposition: attachment. Ninguno viene en base64 ni envuelto en
JSON: el único campo base64 de todo el API es qr_image.
| Ruta | Content-Type |
Qué es |
|---|---|---|
/xml |
application/xml |
El UBL firmado. Es el documento legal. |
/pdf |
application/pdf |
La representación gráfica. Dato derivado. |
/attached-document |
application/xml |
El contenedor que se le entrega al adquirente. |
/application-response |
application/xml |
El acuse de la DIAN. |
/xml — el documento legal
Sección titulada «/xml — el documento legal»Es el UBL 2.1 con la firma XAdES: exactamente los bytes que se le transmitieron a la DIAN. No es una copia ni una reconstrucción. Cuando alguien —una auditoría, el contador, el mismo adquirente— pide «la factura electrónica», esto es lo que pide.
Content-Type: application/xmlContent-Disposition: attachment; filename="SETP990000841.xml"El nombre es el del archivo guardado, <full_number>.xml.
Responde 404 NOT_FOUND con El documento no tiene xml disponible
mientras el documento no se haya firmado.
/pdf — la representación gráfica
Sección titulada «/pdf — la representación gráfica»El papel: A4 con el logo del emisor, el detalle, los totales, el CUFE, el QR y los datos de la resolución. No tiene valor legal por sí solo; el XML lo tiene.
Content-Type: application/pdfContent-Disposition: attachment; filename="SETP990000841.pdf"Es el único de los cuatro que se vuelve a dibujar si falta. Si el
archivo no está guardado —porque el emisor pidió send_email: false y
nunca hizo falta, o porque la lectura falla— se redibuja al vuelo desde
el documento firmado, con el qr_content guardado, y se guarda. Negar un
PDF que se puede reconstruir en un segundo no le sirve a nadie.
Para redibujarlo hace falta el XML firmado y el estado VALIDATED. Si no
los hay: 404 NOT_FOUND con
El PDF se genera cuando la DIAN valida el documento.
Si el emisor subió su propio PDF (ver más abajo), esta ruta devuelve ese, no el nuestro.
/attached-document — el que se le entrega al cliente
Sección titulada «/attached-document — el que se le entrega al cliente»Es el contenedor AttachedDocument del Anexo 1.9: un XML que envuelve,
como CDATA, el documento firmado y el ApplicationResponse de la
DIAN. Es lo que va dentro del ZIP del correo al adquirente, y lo que él
carga en su sistema de recepción — un solo archivo que trae la factura y
la prueba de que la DIAN la aceptó.
Content-Type: application/xmlContent-Disposition: attachment; filename="ad-SETP990000841.xml"Solo existe si la DIAN devolvió ApplicationResponse. Sin eso, no hay
qué envolver. Mientras tanto: 404 NOT_FOUND con
El documento no tiene attached-document disponible.
/application-response — el acuse
Sección titulada «/application-response — el acuse»La respuesta que devolvió la DIAN al validar el documento: el
ApplicationResponse tal cual, sin tocar. Es la prueba de la aceptación.
Sirve para archivarlo por tu cuenta y para leer el detalle de lo que la
DIAN contestó, más allá del dian_status_code que ya traes en el
documento.
Content-Type: application/xmlContent-Disposition: attachment; filename="application-response.xml"Se guarda solo cuando la respuesta de la DIAN lo trae. Si no:
404 NOT_FOUND con El documento no tiene application-response disponible.
Reenviar por correo
Sección titulada «Reenviar por correo»Dos rutas para lo mismo, y la segunda además cambia el PDF.
Reenvío simple
Sección titulada «Reenvío simple»POST/v1/documents/:id/resend-email
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
email |
string | No | Destino. Si se omite, va al correo del adquirente que quedó en el documento. |
Admite varios destinos separados por coma, y el formato con nombre visible. Las tres formas valen:
contabilidad@elpoblado.com.coContabilidad <contabilidad@elpoblado.com.co>cliente@ejemplo.com, contador@ejemplo.comDiez destinos como máximo. Si uno solo de la lista está mal escrito se
rechaza la petición entera, con 422 y el que falla nombrado en
errors[]: es preferible a mandar el documento a medias y que no te
enteres.
curl -X POST https://sandbox.facturacion.misofk.com/v1/documents/b1f3a7d0-9c42-4e18-8a5b-6d0e2f4c9a11/resend-email \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "contabilidad@elpoblado.com.co" }'Responde 201:
{ "queued": true, "email": "contabilidad@elpoblado.com.co" }Tres efectos que conviene tener claros:
- Si mandas un
emaildistinto al que tenía el documento, se sobrescribe el correo del adquirente en el documento. La entrega lee de ahí, y las siguientes también. - Se limpia el
email_erroranterior. - Se fuerza el envío, aunque el documento se hubiera emitido con
send_email: false.
Reenvío con tu propia representación gráfica
Sección titulada «Reenvío con tu propia representación gráfica»POST/v1/documents/:id/email
Content-Type: multipart/form-data.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
file |
archivo | No | Tu PDF. Se comprueba que empiece por %PDF. |
email |
texto | No | Destino; por defecto el del adquirente. |
curl -X POST https://sandbox.facturacion.misofk.com/v1/documents/b1f3a7d0-9c42-4e18-8a5b-6d0e2f4c9a11/email \ -H "Authorization: Bearer $TOKEN" \ -F "file=@factura-con-mi-diseno.pdf" \ -F "email=contabilidad@elpoblado.com.co"Sin file hace exactamente lo mismo que resend-email. Con file, ese
PDF va en el correo y sustituye al nuestro.
Sirve para dos casos: emitiste con send_email: false y ahora quieres
que lo mandemos nosotros, o solo quieres cambiar el diseño del papel.
Errores del reenvío
Sección titulada «Errores del reenvío»| Código | code |
Mensaje |
|---|---|---|
404 |
NOT_FOUND |
Documento no encontrado |
422 |
VALIDATION |
Solo se reenvía un documento validado (actual: SENT) |
422 |
VALIDATION |
El documento aún no tiene contenedor de entrega generado |
422 |
VALIDATION |
Indica el correo de destino: el adquirente no tiene uno registrado |
422 |
VALIDATION |
El archivo no es un PDF — solo en /email |
422 |
VALIDATION |
El documento aún no tiene XML firmado — solo en /email, al subir archivo |
El segundo es el que más sorprende: el correo lleva el AttachedDocument
adentro, así que hasta que ese contenedor no existe no hay nada que
mandar. Es el mismo 404 de /attached-document, visto desde el otro
lado.