Crear sujeto excluido
Emite una factura de sujeto excluido cuando tu empresa compra un bien o servicio a un proveedor que no es contribuyente de IVA. Úsalo desde tu ERP, Saas o módulo de cuentas por pagar al registrar esa compra.
En lugar de armar el DTE tipo 14, manejar reglas de holgura o redondeo para retención de renta, firmar con certificado y transmitir a Hacienda, solo envías proveedor, ítems, si retienes renta y los pagos. Lumen reserva el correlativo, firma, transmite y te devuelve PDF/JSON con URLs prefirmadas.
Método: POST
Endpoint
Section titled “Endpoint”https://api-sandbox.lumendte.com/v1/excluded-taxpayershttps://api.lumendte.com/v1/excluded-taxpayersHeaders
Section titled “Headers”| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
Authorization | string | Sí | Bearer <access_token> (Client Credentials) |
x-company-tax-number | string | Sí | NRC de la empresa compradora (con o sin guiones) |
x-establishment-code | string | Sí | Código dado por MH para el establecimiento (ej. M001) |
x-point-of-sale-code | string | Sí | Código dado por MH para el punto de venta (ej. P001) |
Payload mínimo
Section titled “Payload mínimo”El proveedor es obligatorio. Este es el payload mínimo para emitir a contado sin retención de renta:
{ "supplier": { "name": "Juan Perez", "documentType": "DUI", "documentNumber": "01010101-1", "address": { "complement": "Col. Escalón, San Salvador", "departmentCode": "06", "districtCode": "13" } }, "items": [ { "description": "Servicio de consultoría", "quantity": 1, "unitPrice": 100.0 } ], "withholdIncomeTax": false, "payments": [ { "paymentCode": "01", "amount": 100.0 } ]}Respuesta exitosa
Section titled “Respuesta exitosa”Status: 201 Created
Guarda generationCode y controlNumber. Las URLs pdfUrl y jsonUrl expiran en 15 minutos: descárgalas o reenvíalas de inmediato desde tu backend. No las persistas en tu base de datos para uso posterior.
El campo status indica el resultado:
status | Cuándo aplica |
|---|---|
TRANSMITTED | El DTE se firmó y se envió a Hacienda |
DRAFT | Solo en sandbox, sin credenciales de facturación y certificado: no se firma ni se transmite |
Transmitida (TRANSMITTED)
Section titled “Transmitida (TRANSMITTED)”{ "status": "TRANSMITTED", "generationCode": "FF84E5DB-79C5-42CE-B415-EC510C53EFB5", "controlNumber": "DTE-14-M001P001-000000000000001", "receivedStamp": "20219E9D4DC0292F4681AD759B0B0F5CA99DC23G", "environment": "SANDBOX", "pdfUrl": "https://files.example.com/invoices/1/FF84E5DB-79C5-42CE-B415-EC510C53EFB5.pdf?X-Amz-Expires=900", "jsonUrl": "https://files.example.com/invoices/1/FF84E5DB-79C5-42CE-B415-EC510C53EFB5.json?X-Amz-Expires=900"}Borrador sandbox (DRAFT)
Section titled “Borrador sandbox (DRAFT)”En sandbox sin credenciales listas, Lumen crea el documento como borrador: no llama a firma ni a Hacienda. receivedStamp es null. El PDF y el JSON sí quedan disponibles.
{ "status": "DRAFT", "generationCode": "FF84E5DB-79C5-42CE-B415-EC510C53EFB5", "controlNumber": "DTE-14-M001P001-000000000000001", "receivedStamp": null, "environment": "SANDBOX", "pdfUrl": "https://files.example.com/invoices/1/FF84E5DB-79C5-42CE-B415-EC510C53EFB5.pdf?X-Amz-Expires=900", "jsonUrl": "https://files.example.com/invoices/1/FF84E5DB-79C5-42CE-B415-EC510C53EFB5.json?X-Amz-Expires=900"}environment: SANDBOX o PRODUCTION.
Estructura completa del payload
Section titled “Estructura completa del payload”Si necesitas contacto del proveedor, actividad económica, descuentos, tipo de ítem o pagos a crédito, envía el objeto completo. Con withholdIncomeTax: true, Lumen aplica retención de renta del 10% y la resta del total a pagar: el monto de payments debe ser lo que efectivamente pagas al proveedor.
{ "supplier": { "name": "Juan Perez", "email": "juan.perez@example.com", "phone": "7777-7777", "documentType": "DUI", "documentNumber": "01010101-1", "economicActivityCode": "62010", "address": { "complement": "Col. Escalón, San Salvador", "departmentCode": "06", "districtCode": "13" } }, "items": [ { "sku": "SERV-001", "description": "Servicio de consultoría", "quantity": 1, "unitPrice": 100.0, "discountAmount": 0, "itemType": "SERVICE", "unitOfMeasure": "59" } ], "withholdIncomeTax": true, "payments": [ { "paymentCode": "01", "amount": 90.0 } ]}En este ejemplo: subtotal 100, retención 10, total a pagar 90.
supplier
Section titled “supplier”Proveedor sujeto excluido. Siempre obligatorio.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre completo del proveedor |
documentType | string | Sí | DUI, NIT, PASSPORT, RESIDENT_CARD, OTHER |
documentNumber | string | Sí | Número de documento (DUI con o sin guiones; NIT con guiones) |
address.complement | string | Sí | Complemento de dirección (calle, colonia, etc.) |
address.departmentCode | string | Sí | Código de departamento. Ver Departamentos |
address.districtCode | string | Sí | Código de distrito. Ver Distritos |
email | string | No | Correo del proveedor |
phone | string | No | Teléfono nacional o internacional (ej. 7777-7777, +14155552671) |
economicActivityCode | string | No | Código de actividad económica (1–5). Ver Actividades económicas |
Líneas del documento. Mínimo 1, máximo 2000.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
description | string | Sí | Descripción del ítem |
quantity | number | Sí | Cantidad (> 0) |
unitPrice | number | Sí | Precio unitario de compra sin IVA (> 0) |
sku | string | null | No | Código interno del producto |
discountAmount | number | No | Descuento monetario de la línea (≥ 0). Default: 0. Compra = quantity × unitPrice − discountAmount |
itemType | string | No | GOODS, SERVICE (default), BOTH |
unitOfMeasure | string | No | Unidad de medida del producto. Default: "59" (Unidad). Ver Unidades de medida |
Significados de itemType:
| Valor | Significado |
|---|---|
GOODS | Productos o bienes |
SERVICE | Servicio |
BOTH | Implica tanto servicio como producto a la vez |
withholdIncomeTax
Section titled “withholdIncomeTax”| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
withholdIncomeTax | boolean | Sí | Si true, Lumen aplica retención de renta del 10% y la resta del total a pagar |
payments
Section titled “payments”Formas de pago. Mínimo 1. Puedes enviar más de una si la compra se pagó con varios medios.
Lumen establece la condición de la operación (CAT-016) automáticamente según los pagos enviados:
| Pagos enviados | Condición |
|---|---|
Solo contado (cualquier código ≠ 13) | Contado |
Solo crédito (13) | Crédito |
Crédito (13) + contado | Mixto |
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
paymentCode | string | Sí | Código de forma de pago. Ver Formas de pago |
amount | number | Sí | Monto del pago. Envíalo siempre con el valor real de esa forma de pago |
reference | string | No | Referencia o código de autorización. Se omite en efectivo (01) y en crédito puro |
creditTerm | string | null | Condicional | Tipo de plazo CAT-018. Requerido si paymentCode es 13 (ej. 01 = Días) |
creditPeriod | number | null | Condicional | Cantidad de días/meses/años según creditTerm (1–999). Requerido si paymentCode es 13 |
Cuando paymentCode es 13 (cuentas por pagar), debes indicar plazo y periodo. Ejemplo para un pago a crédito de 30 días:
{ "payments": [ { "paymentCode": "13", "amount": 150.0, "creditTerm": "01", "creditPeriod": 30 } ]}creditTerm (01) = días; creditPeriod (30) = 30 días de plazo. Envía el monto real; en crédito puro Lumen envía montoPago: 0.00 al MH.
Ejemplo de Solicitud
Section titled “Ejemplo de Solicitud”curl -X POST https://api-sandbox.lumendte.com/v1/excluded-taxpayers \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer tu_access_token" \ -H "x-company-tax-number: 123456-7" \ -H "x-establishment-code: M001" \ -H "x-point-of-sale-code: P001" \ -d '{ "supplier": { "name": "Juan Perez", "documentType": "DUI", "documentNumber": "01010101-1", "address": { "complement": "Col. Escalón, San Salvador", "departmentCode": "06", "districtCode": "13" } }, "items": [ { "description": "Servicio de consultoría", "quantity": 1, "unitPrice": 100.0 } ], "withholdIncomeTax": false, "payments": [ { "paymentCode": "01", "amount": 100.0 } ] }'const axios = require("axios");
const config = { method: "post", url: "https://api-sandbox.lumendte.com/v1/excluded-taxpayers", headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: "Bearer tu_access_token", "x-company-tax-number": "123456-7", "x-establishment-code": "M001", "x-point-of-sale-code": "P001", }, data: { supplier: { name: "Juan Perez", documentType: "DUI", documentNumber: "01010101-1", address: { complement: "Col. Escalón, San Salvador", departmentCode: "06", districtCode: "13", }, }, items: [ { description: "Servicio de consultoría", quantity: 1, unitPrice: 100.0, }, ], withholdIncomeTax: false, payments: [ { paymentCode: "01", amount: 100.0, }, ], },};
axios(config) .then((response) => { console.log( "Sujeto excluido aceptado:", response.data.controlNumber, response.data.pdfUrl, ); }) .catch((error) => { console.error( "Error en la solicitud:", error.response ? error.response.data : error.message, ); });import requests
response = requests.post( 'https://api-sandbox.lumendte.com/v1/excluded-taxpayers', headers={ 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'Bearer tu_access_token', 'x-company-tax-number': '123456-7', 'x-establishment-code': 'M001', 'x-point-of-sale-code': 'P001', }, json={ 'supplier': { 'name': 'Juan Perez', 'documentType': 'DUI', 'documentNumber': '01010101-1', 'address': { 'complement': 'Col. Escalón, San Salvador', 'departmentCode': '06', 'districtCode': '13', }, }, 'items': [ { 'description': 'Servicio de consultoría', 'quantity': 1, 'unitPrice': 100.0, }, ], 'withholdIncomeTax': False, 'payments': [ { 'paymentCode': '01', 'amount': 100.0, }, ], },)
if response.ok: data = response.json() print('Sujeto excluido aceptado:', data['controlNumber'], data['pdfUrl'])else: print('Error en la solicitud:', response.text)Errores frecuentes
Section titled “Errores frecuentes”400 — Payload incompleto o inválido
Section titled “400 — Payload incompleto o inválido”Faltan campos del proveedor, withholdIncomeTax no es booleano, o no hay ítems.
{ "errorCode": "INVALID_PARAMETERS", "message": [ "supplier.name should not be empty", "supplier.address.districtCode should not be empty", "withholdIncomeTax must be a boolean value", "items must contain at least 1 elements" ], "error": "Bad Request", "statusCode": 400}Fix: Completa supplier (nombre, documento y dirección), envía withholdIncomeTax como true o false, e incluye al menos un ítem. Si retienes renta, el amount de payments debe ser el total a pagar (subtotal − 10%).
422 — Rechazo de Hacienda
Section titled “422 — Rechazo de Hacienda”El MH rechazó la recepción (contribuyente inactivo, normativa o autorización de emisión).
{ "errorCode": "MH_RECEPTION_TAXPAYER_ERROR", "message": "The taxpayer is not active at the tax authority.", "statusCode": 422}Fix: Verifica que la empresa esté activa para emitir factura electrónica y que la configuración esté lista para el ambiente Sandbox o Producción.