Enviar factura electrónica

Reporta a la DIAN una factura electrónica de venta y devuelve su CUFE.

POST /api/DocumentoFE

Es la ruta de la función, y no cambia entre ambientes. La URL base con la que la ejecutas aquí es la del sandbox. Es la URL del sandbox y no corresponde a la etapa productiva de la integración. La URL base de producción se te entrega al adquirir el servicio.

¿Es tu primer contacto con esta parte de la plataforma? Empieza por Facturación electrónica, donde se explica qué documentos existen, cómo se arma el JSON y qué valida el servidor antes de que ejecutes nada.

Es el documento central de la facturación electrónica: tddocumentoelectronico en 01. El sandbox lo valida, lo reporta a la DIAN y devuelve su CUFE.

Un documento aceptado con observaciones es válido: las observaciones no lo invalidan, pero conviene leerlas. Cómo se construye y se firma el documento está en el concepto del grupo.

Cómo resuelve el sandbox esta función

Emisión de un documento a la DIAN

Lo primero que se mira es la numeración del documento. Si nunca se reportó, el documento sigue el proceso completo. Si ya se reportó, se compara con el que está guardado: llegando igual responde 200 con el estado del documento, su UUID y el documento adjunto, sin volver a reportarlo ni gastar otro consecutivo; llegando con datos distintos responde 409 con la regla 90 de la DIAN y entrega el XML del documento que sí quedó reportado. Para el documento nuevo siguen las validaciones: un incumplimiento responde 400 con una entrada por regla, cada una con su código de la DIAN, su código de InSoft y su mensaje. Solo cuando las pasa se construye el documento electrónico, se firma, se reporta a la DIAN y se espera su respuesta. Si la DIAN lo rechaza, el 400 trae sus mensajes; si no se pudo establecer conexión con ella, responde también 400 pidiendo reintentar más tarde, y en ese caso el documento no quedó reportado. Las validaciones van antes de construir, así que un documento que no va a ser aceptado se rechaza sin gastar un consecutivo.

Emisión de un documento a la DIANLo primero que se mira es la numeración del documento. Si nunca se reportó, el documento sigue el proceso completo. Si ya se reportó, se compara con el que está guardado: llegando igual responde 200 con el estado del documento, su UUID y el documento adjunto, sin volver a reportarlo ni gastar otro consecutivo; llegando con datos distintos responde 409 con la regla 90 de la DIAN y entrega el XML del documento que sí quedó reportado. Para el documento nuevo siguen las validaciones: un incumplimiento responde 400 con una entrada por regla, cada una con su código de la DIAN, su código de InSoft y su mensaje. Solo cuando las pasa se construye el documento electrónico, se firma, se reporta a la DIAN y se espera su respuesta. Si la DIAN lo rechaza, el 400 trae sus mensajes; si no se pudo establecer conexión con ella, responde también 400 pidiendo reintentar más tarde, y en ese caso el documento no quedó reportado. Las validaciones van antes de construir, así que un documento que no va a ser aceptado se rechaza sin gastar un consecutivo.SÍNOSÍNONOSÍNOSÍEl documento llega en JSON¿Ya se reportó esanumeración?¿Llega igualque antes?¿Cumple las reglas?200Estado, UUID y documentoadjunto, sin volvera reportarlo409Regla 90 · entrega el XMLdel documentoConstruye el documentoy lo firma, lo reportay espera a la DIAN400Una entrada por reglaincumplida, con su códigoDIAN y su código InSoft¿La DIAN lo aceptó?400El rechazo de la DIAN, o«intente más tarde» sino hubo conexión200Estado del documento, su UUIDy el documento adjuntoLEYENDAInicio y finPasoDecisiónError

Desliza el diagrama para verlo completo.

Ver la fuente Mermaid del diagrama
flowchart TD
    A(["El documento llega en JSON"]) --> B{"¿Ya se reportó esa numeración?"}
    B -- Sí --> G{"¿Llega igual que antes?"}
    G -- Sí --> R0(["200 · estado, UUID y documento adjunto,<br/>sin volver a reportarlo"])
    G -- No --> R1(["409 · regla 90, entrega el XML del documento"])
    B -- No --> C{"¿Cumple las reglas?"}
    C -- No --> R2(["400 · una entrada por regla incumplida,<br/>con su código DIAN y su código InSoft"])
    C -- Sí --> D["Construye el documento y lo firma,<br/>lo reporta y espera a la DIAN"]
    D --> E{"¿La DIAN lo aceptó?"}
    E -- No --> R3(["400 · el rechazo de la DIAN, o «intente más tarde»<br/>si no hubo conexión"])
    E -- Sí --> H(["200 · estado del documento, su UUID<br/>y el documento adjunto"])

Datos que recibe

Encabezado

DatoTipoDescripción
Authorization*string

Credencial de la petición, con el prefijo Bearer. En el sandbox la pone el portal por ti y la renueva antes de cada ejecución; en producción la controlas tú, con el JWT que genera tu integración a partir de sus credenciales — ver Credenciales y JWT.

Ejemplo:Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6...

Cuerpo

DatoTipoDescripción
tddocumentoelectronico*string

Tipo de documento electrónico. Es el campo que decide qué valida la DIAN y con qué resolución se numera.

Ver los 8 valores admitidos
  • 01 · Factura electrónica de venta
  • 02 · Factura electrónica de venta - exportación
  • 03 · Instrumento electrónico de transmisión
  • 04 · Factura electrónica de venta - tipo 04
  • 05 · Documento soporte en adquisiciones a no obligados a facturar
  • 91 · Nota crédito
  • 92 · Nota débito
  • 95 · Nota de ajuste del documento soporte
tdoperacionfe*string

Tipo de operación. Define que bloques adicionales exige la DIAN dentro de cada item.

Ejemplo:10

Ver los 7 valores admitidos
  • 09 · AIU — Administración, Imprevistos y Utilidad
  • 10 · Estándar — venta normal de bienes y servicios
  • 11 · Mandatos — exige `items[].mandante`
  • 12 · Transporte — exige `items[].datostransporte`
  • 14 · Actos notariales
  • 15 · Compra de divisas
  • 16 · Venta de divisas
numerodocumento*string

Número completo del documento: prefijo de la resolución más consecutivo. El valor <auto> le pide al sandbox que lo numere con su propia resolución.

Ejemplo:<auto>

fechadocumentodate-time

Fecha y hora de emisión. Es opcional: si no la envías, el PT le asigna la de ahora, el momento en que recibe el documento, y es lo que hacen los ejemplos —una fecha escrita a mano envejece y termina fuera de la vigencia de la resolución—. Si la envías, va en ISO 8601 con zona (2026-08-06T10:30:00-05:00); la DIAN rechaza la fecha futura y la que caiga fuera de esa vigencia.

Ejemplo:2026-08-06T10:30:00-05:00

qdecimalesnumber

Decimales con los que se calculan los totales y el UUID. Por defecto 2, que es con lo que van los ejemplos: solo hace falta enviarlo para trabajar con otra precisión.

Ejemplo:2

emisor*TTercero

Quien emite el documento. En el sandbox su identidad se reemplaza por la de la empresa de pruebas; la ubicación, las responsabilidades fiscales y el contacto se conservan.

emisor.ubicacion*TUbicacion

Dirección comercial. Va con el código de municipio (17001) y el de departamento (17); basta el código, porque el PT completa los dos nombres. De qué listado salen se explica en el concepto del grupo.

emisor.ubicacionfiscalTUbicacion

Dirección fiscal. La DIAN la exige en la factura estándar; en documento soporte y nota de ajuste se omite. Si no se envía se asume igual a ubicacion.

emisor.tdresponsabilidadfiscales*Array<string>

Responsabilidades fiscales del emisor según el RUT.

Ver los 5 valores admitidos
  • O-13 · Gran contribuyente
  • O-15 · Autorretenedor
  • O-23 · Agente de retención de IVA
  • O-47 · Regimen simple de tributacion
  • R-99-PN · No aplica / otros
emisor.tributoresponsable*string

Tributo del que el emisor es responsable.

Ver los 4 valores admitidos
  • 01 · IVA
  • 02 · INC
  • ZA · IVA e INC
  • ZZ · No aplica
emisor.contacto.email*string

Correo del emisor. Es obligatorio en facturación electrónica: es a donde la DIAN notifica.

receptor*TTercero

A quien se le emite. Misma estructura del emisor y mismo tratamiento en el sandbox.

resolucionTResolucion

Resolución de numeración con la que se emite. En el envío desde el sandbox el bloque entero se reemplaza, envíes lo que envíes: en una factura o un documento soporte por la que el sandbox tiene registrada, y en una nota por su prefijo de nota. Por eso los ejemplos lo publican con esos campos marcados como <Lo sobrescribe el sandbox>: el rango y la vigencia son valores reales, y lo marcado dice quién lo pone. En producción es tu resolución, y la generación del XML sí la exige completa.

items*Array<TItem>

Líneas del documento. Al menos una, con cantidad mayor que cero.

items[].nombre*Array<string>

Descripción de la línea. Es un arreglo porque la DIAN admite varias líneas de descripción.

items[].unidad*string

Unidad de medida en código UNECE.

Ejemplo:EA

Ver los 6 valores admitidos
  • EA · Cada / unidad
  • KGM · Kilogramo
  • LTR · Litro
  • MTR · Metro
  • HUR · Hora
  • NIU · Número de unidades internacionales
items[].tributosArray<TImpuesto>

Impuestos y retenciones de la línea. Cada uno con clase, valorbase y valor.

Ver los 12 valores admitidos
  • 01 · IVA
  • 02 · IC — Impuesto al consumo
  • 03 · ICA
  • 04 · INC
  • 05 · ReteIVA
  • 06 · ReteRenta
  • 07 · ReteICA
  • 21 · Timbre — exige `precio`
  • 22 · INC Bolsas — exige `precio`
  • 34 · IBUA
  • 35 · ICUI
  • ZZ · Otro tributo
resumentributos*Array<TImpuesto>

Consolidado de tributos del documento. La DIAN valida que coincida con la suma de los tributos de los items.

mediosdepago*Array<TMedioPago>

Como se paga el documento. fechapago es obligatoria cuando tdformapago es crédito, y va en ISO 8601 como toda fecha del documento. tdmediopago es opcional: si no llega, o llega con un código que no está en el catálogo, el PT asume 1 — Instrumento no definido. Los 76 códigos del catálogo están en la ficha del objeto TMedioPago.

Ver los 6 valores admitidos
  • 1 · tdformapago — Contado
  • 2 · tdformapago — Credito
  • 10 · tdmediopago — Efectivo
  • 42 · tdmediopago — Consignacion bancaria
  • 49 · tdmediopago — Tarjeta debito
  • ZZZ · tdmediopago — Otro
descuentoscargosArray<TDescuentoCargo>

Descuentos y recargos a nivel de documento. Si no se indica tddescuento, el PT lo asigna según corresponda.

anticiposArray<TAnticipo>

Anticipos recibidos. Su total se resta del valor a pagar.

monedaTMoneda

Divisa distinta del peso colombiano, con su tasa de cambio y la fecha de la tasa. Si se envía, el XML incluye los totales también en COP.

totalapagarnumber

Total del documento. Si no se envía, el PT lo calcula desde los items, los tributos, los descuentos y los anticipos.

notasArray<string>

Observaciones libres que se imprimen en la representación grafica.

Lo que el sandbox fuerza

El sandbox emite con una integración y una empresa de pruebas compartidas por todos los desarrolladores. Lo que envíes en estos campos no se usa: se sustituye antes de reportar el documento a la DIAN. Todo lo demás viaja tal como lo dejes.

  • tdambiente
    2 — Pruebas (habilitación)

    El sandbox solo emite contra el ambiente de habilitación de la DIAN, sin importar lo que llegue en el documento.

  • emisor.nit
    NIT de la empresa de pruebas

    Es el único NIT que el sandbox tiene habilitado ante la DIAN: un emisor distinto se rechaza antes de firmar el documento. El resto del emisor —razón social, tipo de persona, ubicación— viaja como lo envíes: si no corresponde al NIT habilitado, la DIAN puede rechazar el documento.

  • receptor.nit
    NIT de InSoft

    Por seguridad, el sandbox no permite emitir documentos a un tercero distinto de InSoft: el receptor se impone siempre, sin importar el que envíes. Así ninguna prueba puede reportar a la DIAN un documento a nombre de alguien que no la autorizó. Es también el NIT que el catálogo de la DIAN te pide para buscar el documento.

  • resolucion
    La del sandbox — el bloque entero, siempre

    No se conserva nada de la que envíes: el sandbox reemplaza el bloque completo antes de verificar el documento. La factura numera con la resolución de facturación que tiene registrada y el documento soporte con la del documento soporte; las notas crédito, débito y de ajuste no consumen resolución y reciben solo su prefijo, uno por tipo. En la generación del XML no se reemplaza nada: ahí la resolución es la que envíes.

  • numerodocumento
    Prefijo de la resolución más el siguiente consecutivo

    Solo cuando llega con el valor <auto>, que es lo que hacen los ejemplos. Cualquier otro valor viaja tal como lo escribas —y entonces respondes tú por que el consecutivo esté dentro del rango y no se repita: un número ya reportado responde 409 con la regla 90 de la DIAN—. No depende de la resolución que envíes, porque esa se reemplaza igual.

  • testsetid
    Vacío

    El testsetid solo interviene en el proceso de habilitación ante la DIAN: es el conjunto de pruebas que un NIT nuevo tiene que procesar con éxito antes de poder emitir de verdad. La empresa del sandbox ya está habilitada y tu integración no se habilita desde aquí, de modo que va vacío y el envío se reporta como cualquier documento.

Ejecutar la función

Ambiente de habilitación de la DIAN · los documentos son reales pero no tienen efectos tributarios

Lo que se envía

Venta de contado de un servicio, con IVA del 19% y numeración automática del sandbox.

Documento que se envía — editalo para armar tu caso de prueba
Se enviara POST https://proveedortecnologico-sandbox.azurewebsites.net/api/DocumentoFE

Es la URL del sandbox y no corresponde a la etapa productiva de la integración. La URL base de producción se te entrega al adquirir el servicio. Lo que si es igual en los dos es la ruta.

Respuesta

Aquí queda tu ejecución: la ruta que viajó, el cuerpo que enviaste, el código con el que respondió el sandbox y el tiempo discriminado. Un error también queda: es lo que se necesita junto al cuerpo que lo produjo.

Exportar a Postman

Descarga esta función como colección de Postman, con los valores que tienes ahora en la barra y tu credencial vigente: se importa y se envía sin configurar nada.

Respuestas

  • 200 La DIAN recibió el documento. En respuesta viajan el UUID generado (CUFE o CUDS), el estado de la DIAN y sus mensajes de validación.
  • 400 El documento no paso las validaciones del PT o de la DIAN. El mensaje indica la regla incumplida.
  • 401 La credencial no llegó, ya venció, o la cuenta no tiene perfil registrado en el sandbox. En producción es además el código con el que se rechaza un emisor que la credencial no tiene autorizado — ver Credenciales y JWT.
  • 500 Falla al firmar o al comunicarse con la DIAN.

Errores frecuentes

  • 401 El desarrollador autenticado no tiene un perfil registrado en el sandbox

    La cuenta se autenticó pero nunca completó el registro de desarrollador. Se resuelve diligenciando el perfil desde el portal.

  • 401 Token de autenticación no válido

    La credencial del sandbox venció —dura una hora—. El portal la renueva sola; con peticiones propias hay que pedir una nueva. En producción la vigencia es la de tu JWT — ver Credenciales y JWT.

  • 400 El total del documento no corresponde con la suma de sus líneas

    totalapagar no cuadra con los items, los tributos y los descuentos. Lo más simple es omitir el campo y dejar que el PT lo calcule.

  • 400 Regla AJ** de la DIAN

    Alguna de las más de setenta validaciones de la DIAN sobre el documento. El mensaje trae el código de la regla; el código de municipio de la ubicación y el correo del receptor son las causas más frecuentes.

  • 500 El sandbox no tiene registrada la configuración SANDBOX - EMPRESA

    Es un problema de montaje del ambiente, no de la petición. Hay que reportarlo al equipo de InSoft.

Ten en cuenta

  • La DIAN exige emisor.ubicacionfiscal en la factura estándar. Es el campo que más rechazos produce cuando se arma el primer documento.
  • Una diferencia de un centavo en los totales cambia el CUFE y la DIAN rechaza el documento: los tributos se calculan con la precisión decimal que declare qdecimales.
  • La ubicación, las responsabilidades fiscales, el tributo responsable, la actividad económica y el contacto del emisor y del receptor no se reemplazan: son parte del caso de prueba y viajan tal como se envien.
  • Los items, los tributos, los descuentos, los anticipos, los medios de pago y los totales viajan sin modificación. Ahí es donde se prueba de verdad la integración.
  • El sandbox emite con una integración compartida por todos los desarrolladores. El token con el que se reporta a la DIAN lo abre el propio servicio y nunca sale hacia el navegador.