openapi: 3.0.3 info: title: LibellumCore API version: 2026.07.01 description: | Documentacion oficial para integracion externa con LibellumCore. Flujo recomendado: 1. Solicitar a Libellum el token Bearer, ambiente y prefijos habilitados. 2. Validar el token con `POST /rest/apikey/validate`. 3. Crear el documento con `POST /rest/document/generate`. 4. Consultar el estado con `GET /rest/document/info/{id}`. 5. Descargar el ZIP cuando el estado sea `COMPLETED` con `GET /rest/document/attachment/{id}`. La API productiva esta en `https://libellumplus.com`. Esta documentacion no debe incluir tokens reales de clientes. servers: - url: https://libellumplus.com description: API productiva tags: - name: Autenticacion description: Validacion del token Bearer entregado por Libellum. - name: Documentos description: Creacion, consulta y descarga de documentos DIAN. - name: Operacion description: Reglas practicas para integracion y soporte. security: - bearerAuth: [] paths: /rest/apikey/validate: post: tags: - Autenticacion summary: Validar token API description: | Verifica que el token Bearer exista, este activo y se encuentre autorizado en el firewall API. Este debe ser el primer llamado de cualquier integracion nueva. Si falla, no se debe intentar crear documentos. responses: "200": description: Token valido. content: application/json: schema: $ref: "#/components/schemas/ApiKeyValidationSuccess" examples: ok: value: message: "hash-de-validacion" "400": description: Token invalido o cliente suspendido para API. content: application/json: schema: $ref: "#/components/schemas/ApiError" examples: invalidKey: value: message: "Api Key Invalida" type: "error" result: "EA01" firewall: value: message: "Empresa con Acceso a Api suspendido, contacte con Soporte Libellum SAS" type: "error" result: "EA02" "401": description: Cabecera Authorization ausente o mal formada. content: application/json: schema: $ref: "#/components/schemas/ApiError" examples: badAuthorization: value: message: "Autorizacion Invalida" type: "error" result: "E001" x-codeSamples: - lang: cURL label: Validar token source: | curl -X POST "https://libellumplus.com/rest/apikey/validate" \ -H "Authorization: Bearer REEMPLAZAR_TOKEN" /rest/document/generate: post: tags: - Documentos summary: Generar documento desde JSON estructurado description: | Recibe un JSON estructurado, genera el XML UBL y deja el documento en cola para envio a la DIAN. Tipos soportados por este endpoint: - Factura electronica de venta (`FV`). - Nota credito electronica (`NC`). - Nota debito electronica (`ND`). El campo `prefijo` debe existir en la configuracion del cliente y determina el tipo real del documento. El campo `numero_documento` debe enviarse sin repetir el prefijo cuando el consecutivo interno del cliente asi lo maneje. Libellum validara contra la resolucion configurada para el prefijo. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/Documento" examples: facturaBasica: summary: Factura electronica con IVA value: prefijo: "FAR" numero_documento: "1001" fecha_emision: "2026-07-01" hora_emision: "10:15:00" fecha_vencimiento: "2026-07-31" codigo_moneda: "COP" orden_compra: "OC-001" codigo_metodo_pago: "1" codigo_medio_pago: "10" adquiriente: razon_social: "CLIENTE DE PRUEBAS SAS" documento: "900000001" dv: 1 tipo_persona: 1 regimen: "48" tipo_identificacion_fiscal: "31" codigo_responsabilidad_fiscal: "R-99-PN" codigo_municipio: "11001" codigo_departamento: "11" nombre_municipio: "Bogota" nombre_departamento: "Bogota D.C." direccion: "Calle 1 # 2-3" codigo_pais: "169" codigo_pais_alfa_2: "CO" codigo_postal: "110111" correo_electronico: "compras@example.com" telefono: "3000000000" total_bruto: 100000 total_cargos: 0 total_descuentos: 0 total_impuestos: 19000 valor_total: 119000 notas: - "Documento de prueba generado por integracion API." items: - codigo_producto: "SERV-001" codigo_unidad_medida: "94" cantidad: 1 valor_unitario: 100000 inc_bolsa: false descripcion: "Servicio de prueba" descripcion_adicional: null marca: null modelo: null codigo_generacion: null descripcion_generacion: null descuentos: [] impuestos: base_imponible: 100000 porcentaje: 19 monto_impuesto: 19000 codigo_impuesto: "01" facturaSinIva: summary: Factura sin IVA value: prefijo: "FAR" numero_documento: "1002" fecha_emision: "2026-07-01" hora_emision: "10:20:00" fecha_vencimiento: "2026-07-31" codigo_moneda: "COP" orden_compra: null codigo_metodo_pago: "1" codigo_medio_pago: "10" adquiriente: razon_social: "CLIENTE SIN IVA SAS" documento: "900000002" dv: 2 tipo_persona: 1 regimen: "48" tipo_identificacion_fiscal: "31" codigo_responsabilidad_fiscal: "R-99-PN" codigo_municipio: "11001" codigo_departamento: "11" nombre_municipio: "Bogota" nombre_departamento: "Bogota D.C." direccion: "Carrera 10 # 20-30" codigo_pais: "169" codigo_pais_alfa_2: "CO" codigo_postal: "110111" correo_electronico: "cliente@example.com" telefono: "3000000001" total_bruto: 50000 total_cargos: 0 total_descuentos: 0 total_impuestos: 0 valor_total: 50000 items: - codigo_producto: "SERV-002" codigo_unidad_medida: "94" cantidad: 1 valor_unitario: 50000 inc_bolsa: false descripcion: "Servicio excluido" descripcion_adicional: null marca: null modelo: null codigo_generacion: null descripcion_generacion: null descuentos: [] facturaConRetenciones: summary: Factura con retenciones value: prefijo: "FAR" numero_documento: "1003" fecha_emision: "2026-07-01" hora_emision: "10:25:00" fecha_vencimiento: "2026-07-31" codigo_moneda: "COP" orden_compra: "OC-RET-001" codigo_metodo_pago: "1" codigo_medio_pago: "10" adquiriente: razon_social: "AGENTE RETENEDOR SAS" documento: "900000003" dv: 3 tipo_persona: 1 regimen: "48" tipo_identificacion_fiscal: "31" codigo_responsabilidad_fiscal: "O-13" codigo_municipio: "11001" codigo_departamento: "11" nombre_municipio: "Bogota" nombre_departamento: "Bogota D.C." direccion: "Avenida 1 # 1-1" codigo_pais: "169" codigo_pais_alfa_2: "CO" codigo_postal: "110111" correo_electronico: "retenciones@example.com" telefono: "3000000002" total_bruto: 1000000 total_cargos: 0 total_descuentos: 0 total_impuestos: 190000 valor_total: 1190000 retefuente: base_imponible: 1000000 porcentaje: 2.5 valor: 25000 reteica: base_imponible: 1000000 porcentaje: 0.966 valor: 9660 reteiva: base_imponible: 190000 porcentaje: 15 valor: 28500 items: - codigo_producto: "SERV-RET" codigo_unidad_medida: "94" cantidad: 1 valor_unitario: 1000000 inc_bolsa: false descripcion: "Servicio sujeto a retenciones" descripcion_adicional: null marca: null modelo: null codigo_generacion: null descripcion_generacion: null descuentos: [] impuestos: base_imponible: 1000000 porcentaje: 19 monto_impuesto: 190000 codigo_impuesto: "01" facturaMonedaExtranjera: summary: Factura en USD value: prefijo: "FAR" numero_documento: "1004" fecha_emision: "2026-07-01" hora_emision: "10:30:00" fecha_vencimiento: "2026-07-31" codigo_moneda: "USD" tasa_cambio: 4100.25 fecha_tasa_cambio: "2026-07-01" orden_compra: "PO-USD-001" codigo_metodo_pago: "1" codigo_medio_pago: "10" adquiriente: razon_social: "CLIENTE EXTERIOR INC" documento: "444444444" dv: null tipo_persona: 1 regimen: "48" tipo_identificacion_fiscal: "42" codigo_responsabilidad_fiscal: "R-99-PN" codigo_municipio: "11001" codigo_departamento: "11" nombre_municipio: "Bogota" nombre_departamento: "Bogota D.C." direccion: "Foreign address" codigo_pais: "249" codigo_pais_alfa_2: "US" codigo_postal: "000000" correo_electronico: "foreign@example.com" telefono: "0000000000" total_bruto: 100 total_cargos: 0 total_descuentos: 0 total_impuestos: 19 valor_total: 119 items: - codigo_producto: "EXP-001" codigo_unidad_medida: "94" cantidad: 1 valor_unitario: 100 inc_bolsa: false descripcion: "Servicio exportado" descripcion_adicional: null marca: null modelo: null codigo_generacion: null descripcion_generacion: null descuentos: [] impuestos: base_imponible: 100 porcentaje: 19 monto_impuesto: 19 codigo_impuesto: "01" notaCredito: summary: Nota credito value: prefijo: "NCRE" numero_documento: "10" fecha_emision: "2026-07-01" hora_emision: "11:00:00" fecha_vencimiento: "2026-07-01" codigo_moneda: "COP" orden_compra: null codigo_metodo_pago: "1" codigo_medio_pago: "10" documento_referencia: motivo: "Devolucion parcial" numero_documento: "FAR1001" algoritmo: "CUFE-SHA384" uuid: "CUFE_O_CUDE_DOCUMENTO_REFERENCIA" fecha: "2026-07-01" adquiriente: razon_social: "CLIENTE DE PRUEBAS SAS" documento: "900000001" dv: 1 tipo_persona: 1 regimen: "48" tipo_identificacion_fiscal: "31" codigo_responsabilidad_fiscal: "R-99-PN" codigo_municipio: "11001" codigo_departamento: "11" nombre_municipio: "Bogota" nombre_departamento: "Bogota D.C." direccion: "Calle 1 # 2-3" codigo_pais: "169" codigo_pais_alfa_2: "CO" codigo_postal: "110111" correo_electronico: "compras@example.com" telefono: "3000000000" total_bruto: 10000 total_cargos: 0 total_descuentos: 0 total_impuestos: 1900 valor_total: 11900 items: - codigo_producto: "DEV-001" codigo_unidad_medida: "94" cantidad: 1 valor_unitario: 10000 inc_bolsa: false descripcion: "Devolucion parcial" descripcion_adicional: null marca: null modelo: null codigo_generacion: null descripcion_generacion: null descuentos: [] impuestos: base_imponible: 10000 porcentaje: 19 monto_impuesto: 1900 codigo_impuesto: "01" responses: "201": description: Documento recibido y encolado para procesamiento DIAN. content: application/json: schema: $ref: "#/components/schemas/DocumentCreateResponse" examples: created: value: result: true id: 26490001 "400": description: Error de autenticacion o cliente suspendido. content: application/json: schema: $ref: "#/components/schemas/ApiError" "401": description: Cabecera Authorization ausente o mal formada. content: application/json: schema: $ref: "#/components/schemas/ApiError" "422": description: Error de validacion del payload o prefijo no configurado. content: application/json: schema: oneOf: - $ref: "#/components/schemas/ValidationError" - $ref: "#/components/schemas/ApiMessage" examples: requiredField: value: errores: prefijo: - "El campo prefijo es obligatorio." items: - "Debe proporcionar al menos un item." invalidPrefix: value: message: "Prefijo invalido." x-codeSamples: - lang: cURL label: Crear documento source: | curl -X POST "https://libellumplus.com/rest/document/generate" \ -H "Authorization: Bearer REEMPLAZAR_TOKEN" \ -H "Content-Type: application/json" \ -d @factura.json /rest/document/info/{id}: get: tags: - Documentos summary: Consultar estado de un documento description: | Consulta el estado de procesamiento y respuesta DIAN de un documento creado por el mismo cliente autenticado. Estados: - `IN_PROGRESS`: recibido y pendiente/en proceso de envio. - `COMPLETED`: aceptado o completado por DIAN. - `REJECTED`: rechazado por DIAN o bloqueado por validacion final. - `ERROR_PROCESSING`: error tecnico interno de procesamiento. parameters: - name: id in: path required: true description: Identificador retornado por `POST /rest/document/generate`. schema: type: integer format: int64 responses: "200": description: Estado del documento. content: application/json: schema: $ref: "#/components/schemas/DocumentStatusResponse" examples: inProgress: value: id: 26490001 dian: track_id: null cufe: null codigo_qr: "string" detalles: null estado: "IN_PROGRESS" xml_firmado: null completed: value: id: 26490001 dian: track_id: "a1b2c3d4" cufe: "CUFE_GENERADO_POR_DIAN" codigo_qr: "string" detalles: valido: true descripcion: "Documento aceptado por la DIAN." estado: "COMPLETED" xml_firmado: "PD94bWwgdmVyc2lvbj0iMS4wIj8+..." rejected: value: id: 26490001 dian: track_id: "a1b2c3d4" cufe: null codigo_qr: "string" detalles: valido: false descripcion: "El XML no contiene lineas de factura. Revise que el documento tenga al menos un item antes de enviarlo." estado: "REJECTED" xml_firmado: null "403": description: El documento no pertenece al cliente autenticado. "404": description: Documento no encontrado. x-codeSamples: - lang: cURL label: Consultar estado source: | curl "https://libellumplus.com/rest/document/info/26490001" \ -H "Authorization: Bearer REEMPLAZAR_TOKEN" /rest/document/attachment/{id}: get: tags: - Documentos summary: Descargar ZIP con PDF y AttachedDocument description: | Retorna el ZIP en base64 cuando el documento ya tiene respuesta DIAN. El consumidor debe decodificar el campo `zip` y guardarlo como archivo `.zip`. parameters: - name: id in: path required: true description: Identificador retornado por `POST /rest/document/generate`. schema: type: integer format: int64 responses: "200": description: ZIP disponible en base64. content: application/json: schema: $ref: "#/components/schemas/AttachmentResponse" examples: ok: value: result: true zip: "UEsDBBQAAAAI..." "403": description: Documento inexistente o no autorizado para el cliente autenticado. content: application/json: schema: $ref: "#/components/schemas/AttachmentResponse" examples: forbidden: value: result: false zip: null "404": description: El documento aun no tiene respuesta DIAN para construir el ZIP. content: application/json: schema: $ref: "#/components/schemas/AttachmentResponse" examples: pending: value: result: false zip: null x-codeSamples: - lang: cURL label: Descargar ZIP base64 source: | curl "https://libellumplus.com/rest/document/attachment/26490001" \ -H "Authorization: Bearer REEMPLAZAR_TOKEN" /rest/document/add: post: tags: - Operacion summary: XML directo en base64 description: | Camino alterno para integradores que ya generan XML UBL por su cuenta. Este endpoint recibe el XML en base64 en el campo `document` y lo deja en cola para envio DIAN. Para integraciones nuevas se recomienda `POST /rest/document/generate`, salvo que Libellum confirme explicitamente uso de XML directo. requestBody: required: true content: application/json: schema: type: object required: - document properties: document: type: string description: XML UBL codificado en base64. responses: "201": description: XML recibido. content: application/json: schema: $ref: "#/components/schemas/DocumentCreateResponse" "400": description: Token invalido o suspendido. "401": description: Cabecera Authorization ausente o mal formada. components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: Token description: Token Bearer entregado por Libellum por canal seguro. schemas: ApiKeyValidationSuccess: type: object properties: message: type: string description: Hash de validacion retornado por la plataforma. ApiError: type: object properties: message: type: string type: type: string example: error result: type: string example: EA01 code: type: integer nullable: true ApiMessage: type: object properties: message: type: string ValidationError: type: object properties: errores: type: object additionalProperties: type: array items: type: string DocumentCreateResponse: type: object properties: result: type: boolean example: true id: type: integer format: int64 description: Identificador interno para consultar estado y adjuntos. DocumentStatusResponse: type: object properties: id: type: integer nullable: true dian: $ref: "#/components/schemas/DianStatus" estado: type: string enum: - IN_PROGRESS - COMPLETED - REJECTED - ERROR_PROCESSING nullable: true xml_firmado: type: string nullable: true description: XML firmado en base64 cuando el estado es COMPLETED. DianStatus: type: object nullable: true properties: track_id: type: string nullable: true cufe: type: string nullable: true codigo_qr: type: string nullable: true detalles: nullable: true description: Respuesta DIAN o validacion tecnica registrada por Libellum. AttachmentResponse: type: object properties: result: type: boolean zip: type: string nullable: true description: ZIP codificado en base64. Documento: type: object required: - prefijo - numero_documento - fecha_emision - hora_emision - fecha_vencimiento - codigo_moneda - codigo_metodo_pago - codigo_medio_pago - adquiriente - total_bruto - total_cargos - total_descuentos - total_impuestos - valor_total - items properties: prefijo: type: string maxLength: 10 description: Prefijo configurado para el cliente. Define si es FV, NC o ND. numero_documento: type: string maxLength: 20 description: Consecutivo del documento. fecha_emision: type: string format: date description: Fecha en formato YYYY-MM-DD. hora_emision: type: string pattern: "^\\d{2}:\\d{2}:\\d{2}$" description: Hora en formato HH:MM:SS. fecha_vencimiento: type: string format: date codigo_moneda: type: string maxLength: 3 example: COP tasa_cambio: type: number nullable: true description: Obligatorio cuando `codigo_moneda` no es COP. fecha_tasa_cambio: type: string format: date nullable: true description: Obligatorio cuando `codigo_moneda` no es COP. orden_compra: type: string nullable: true maxLength: 20 codigo_metodo_pago: type: string maxLength: 3 description: Codigo DIAN del metodo de pago. codigo_medio_pago: type: string maxLength: 3 description: Codigo DIAN del medio de pago. adquiriente: $ref: "#/components/schemas/Adquiriente" total_bruto: type: number total_cargos: type: number total_descuentos: type: number total_impuestos: type: number valor_total: type: number retefuente: $ref: "#/components/schemas/Retencion" reteica: $ref: "#/components/schemas/Retencion" reteiva: $ref: "#/components/schemas/Retencion" documento_referencia: $ref: "#/components/schemas/DocumentoReferencia" notas: type: array nullable: true items: type: string items: type: array minItems: 1 items: $ref: "#/components/schemas/Item" Adquiriente: type: object required: - razon_social - documento - regimen - tipo_identificacion_fiscal - codigo_responsabilidad_fiscal - codigo_municipio - codigo_departamento - direccion - codigo_pais - codigo_pais_alfa_2 - codigo_postal properties: razon_social: type: string maxLength: 200 documento: type: string maxLength: 12 dv: type: number nullable: true maximum: 9 tipo_persona: type: number nullable: true description: 1 juridica, 2 natural, segun configuracion DIAN usada por el cliente. regimen: type: string maxLength: 2 tipo_identificacion_fiscal: type: string maxLength: 2 example: "31" codigo_responsabilidad_fiscal: type: string maxLength: 50 example: "R-99-PN" codigo_municipio: type: string maxLength: 5 codigo_departamento: type: string maxLength: 2 nombre_municipio: type: string nullable: true maxLength: 255 nombre_departamento: type: string nullable: true maxLength: 255 direccion: type: string maxLength: 100 codigo_pais: type: string maxLength: 3 example: "169" codigo_pais_alfa_2: type: string maxLength: 2 example: CO codigo_postal: type: string maxLength: 8 correo_electronico: type: string format: email nullable: true maxLength: 200 telefono: type: string nullable: true maxLength: 16 Item: type: object required: - codigo_producto - codigo_unidad_medida - cantidad - valor_unitario - inc_bolsa - descripcion properties: codigo_producto: type: string maxLength: 255 codigo_unidad_medida: type: string maxLength: 255 example: "94" cantidad: type: number valor_unitario: type: number inc_bolsa: type: boolean descripcion: type: string maxLength: 255 descripcion_adicional: type: string nullable: true maxLength: 255 marca: type: string nullable: true maxLength: 255 modelo: type: string nullable: true maxLength: 255 codigo_generacion: type: string nullable: true maxLength: 255 descripcion_generacion: type: string nullable: true maxLength: 255 descuentos: type: array nullable: true items: $ref: "#/components/schemas/ItemDescuento" impuestos: $ref: "#/components/schemas/ItemImpuesto" ItemDescuento: type: object required: - base_imponible - porcentaje - monto_descuento - valor_bruto properties: base_imponible: type: number porcentaje: type: number monto_descuento: type: number valor_bruto: type: number ItemImpuesto: type: object nullable: true required: - base_imponible - porcentaje - monto_impuesto - codigo_impuesto properties: base_imponible: type: number porcentaje: type: number monto_impuesto: type: number codigo_impuesto: type: string example: "01" Retencion: type: object nullable: true required: - base_imponible - porcentaje - valor properties: base_imponible: type: number porcentaje: type: number valor: type: number DocumentoReferencia: type: object nullable: true required: - motivo - numero_documento - algoritmo - uuid - fecha properties: motivo: type: string description: Motivo de la nota credito. numero_documento: type: string description: Numero del documento referenciado. algoritmo: type: string example: "CUFE-SHA384" uuid: type: string description: CUFE/CUDE del documento referenciado. fecha: type: string format: date x-integration-notes: entrega_cliente: - "URL documentacion: https://apidoc.libellum.co/" - "URL base API: https://libellumplus.com" - "Token Bearer por canal seguro." - "Prefijos habilitados y ambiente confirmado por Libellum." errores_comunes: - codigo: "EA01" significado: "Token no existe en Libellum." accion: "Verificar token entregado." - codigo: "EA02" significado: "Cliente suspendido o token no autorizado en firewall API." accion: "Solicitar activacion a soporte Libellum." - codigo: "E001" significado: "Authorization no tiene formato Bearer." accion: "Enviar Authorization: Bearer TOKEN." - mensaje: "Prefijo invalido." accion: "Usar un prefijo configurado para el cliente y el ambiente correcto." - estado: "REJECTED" accion: "Consultar dian.detalles.descripcion y corregir el documento antes de reenviar."