Sujeto Excluido (14)
El DTE de Sujeto Excluido (tipo 14) es un documento que emite el comprador, no el vendedor. Se usa cuando tu empresa compra a una persona natural no contribuyente IVA (sin NRC) — típicamente servicios profesionales, arrendamientos, compra de bienes de pequeños productores, etc.
A diferencia de Factura 01 y CCF 03 donde el flujo es "yo vendo y emito", en SUEX el flujo es "yo compro y documento la compra" — de ahí que use el modelo PurchaseHeader internamente y no SalesHeader.
Cuándo usar SUEX
- Pago a profesionales independientes sin NRC.
- Compra a proveedores personas naturales no inscritos en IVA.
- Arrendamientos a personas naturales.
- Cualquier compra a un "Sujeto Excluido" en términos fiscales MH.
Retención renta 10% automática
Cuando una línea está marcada con is_service: true, el API aplica automáticamente una retención del 10% del valor del servicio como anticipo de renta. Esta retención la paga tu empresa al MH mensualmente; el sujeto excluido recibe el monto neto (total − retención).
Si la línea es is_service: false (compra de bienes), no hay retención de renta.
Detalles técnicos
| Método | POST |
| URL | https://ocote.io/api/connect/suex |
| Content-Type | application/json |
| Autenticación | Header Authorization: Bearer odt_... |
Request
Campos principales
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
lines | array | Sí | Líneas del documento. Al menos una. |
subject | object | Sí | Datos del sujeto excluido (vendedor). |
external_ref | string | No | Tu identificador idempotente. |
Líneas (lines)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
description | string | Sí | Descripción del bien/servicio. Máx 1 000 caracteres. |
quantity | float | Sí | Cantidad. Debe ser mayor a cero. |
unit_price | float | Sí | Precio unitario. Debe ser mayor a cero. |
is_service | bool | No (default false) | true → aplica retención renta 10%. |
Sujeto (subject)
Todos los campos son del sujeto excluido (el vendedor a quien le compras).
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre completo del sujeto. |
document_type | string | No (default "13") | Tipo de documento identificador. Valores válidos: "02" (Carnet de Residente), "03" (Pasaporte), "13" (DUI), "36" (NIT), "37" (Otro). |
document_no | string | Sí | Número del documento identificador. |
address | string | Sí | Dirección del sujeto. |
department | string | No | Código de departamento MH. Si lo envías, municipality también es obligatorio. |
municipality | string | No | Código de municipio MH. |
phone_number | string | No | Teléfono. A diferencia del customer.phone en Factura/CCF, este campo sí funciona correctamente. |
email | string | No | Correo electrónico. |
Si emites un SUEX con un document_no que ya existe en tu empresa, Ocote actualiza los datos del sujeto (dirección, email, etc.) y reutiliza el registro. Esto evita duplicados en tu base de sujetos.
Response
Estructura idéntica a la de /invoice con los mismos flags de estado (success, dte_success, contingency, rejected, etc.). Ver Respuestas y estados.
A diferencia de /invoice, el response directo de POST /suex no incluye los campos de montos calculados. Para obtener amount, amount_irs (retención renta) y total_pay (monto neto a pagar), consulta el estado del documento con GET /suex/status/{id_or_ref} después de emitir. Ver Consultar estado.
Ejemplo: pago de servicios profesionales
curl -X POST https://ocote.io/api/connect/suex \
-H "Authorization: Bearer odt_xxx" \
-H "Content-Type: application/json" \
-d '{
"external_ref": "SUEX-2026-0015",
"subject": {
"name": "Ana María González Rodríguez",
"document_type": "13",
"document_no": "01234567-8",
"address": "Colonia San Benito, San Salvador",
"department": "06",
"municipality": "14",
"email": "ana.gonzalez@example.com"
},
"lines": [
{
"description": "Asesoría legal corporativa - Marzo 2026",
"quantity": 1,
"unit_price": 1500.00,
"is_service": true
}
]
}'
const { data } = await axios.post(
'https://ocote.io/api/connect/suex',
{
external_ref: 'SUEX-2026-0015',
subject: {
name: 'Ana María González Rodríguez',
document_type: '13',
document_no: '01234567-8',
address: 'Colonia San Benito, San Salvador',
department: '06',
municipality: '14',
email: 'ana.gonzalez@example.com',
},
lines: [
{ description: 'Asesoría legal corporativa - Marzo 2026',
quantity: 1, unit_price: 1500.00, is_service: true },
],
},
{ headers: { Authorization: `Bearer ${process.env.OCOTE_API_KEY}` } }
);
r = requests.post(
"https://ocote.io/api/connect/suex",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"external_ref": "SUEX-2026-0015",
"subject": {
"name": "Ana María González Rodríguez",
"document_type": "13",
"document_no": "01234567-8",
"address": "Colonia San Benito, San Salvador",
"department": "06",
"municipality": "14",
"email": "ana.gonzalez@example.com",
},
"lines": [
{
"description": "Asesoría legal corporativa - Marzo 2026",
"quantity": 1,
"unit_price": 1500.00,
"is_service": True,
},
],
},
)
Consultar los montos calculados
Tras emitir, consulta el estado para ver la retención aplicada:
curl https://ocote.io/api/connect/suex/status/SUEX-2026-0015 \
-H "Authorization: Bearer odt_xxx"
Respuesta:
{
"document_id": "b2c3d4e5-...",
"external_ref": "SUEX-2026-0015",
"doc_type": "14",
"control_number": "DTE-14-M001P001-000000000000015",
"reception_stamp": "20260421...",
"success": true,
"posted": true,
"invalidated": false,
"amount": 1500.00,
"amount_irs": 150.00,
"total_pay": 1350.00,
"suex_name": "Ana María González Rodríguez",
"created": "2026-04-21T10:42:15-06:00",
"posted_date": "2026-04-21T10:42:18-06:00",
"invoice_url": "https://ocote.io/api/v2/suex-history/b2c3d4e5-.../file?type=invoice",
"json_url": "https://ocote.io/api/v2/suex-history/b2c3d4e5-.../file?type=json",
"dte_success": true,
"contingency": false,
"rejected": false,
"dte_state": "",
"dte_message": "",
"observaciones": [],
"codigo_msg": ""
}
Desglose:
amount: 1500.00— valor del servicio declarado.amount_irs: 150.00— 10% de retención renta (1500 × 0.10). Lo paga tu empresa al MH.total_pay: 1350.00— lo que efectivamente transfieres a Ana María.
Ejemplo sin retención: compra de bienes
Si compras bienes (no servicios), marca is_service: false:
{
"external_ref": "SUEX-2026-0016",
"subject": {
"name": "José Pérez",
"document_type": "13",
"document_no": "98765432-1",
"address": "Ilobasco, Cabañas"
},
"lines": [
{
"description": "Maíz blanco - 10 quintales",
"quantity": 10,
"unit_price": 45.00,
"is_service": false
}
]
}
En el status veremos amount_irs: 0.00 y total_pay: 450.00.
Errores de validación específicos
HTTP 400 con detalle en detail:
| Mensaje | Causa |
|---|---|
Debe incluir al menos una línea | lines vacío o ausente. |
Línea N: cantidad debe ser mayor a cero | Algún item con quantity <= 0. |
Línea N: precio unitario debe ser mayor a cero | Algún item con unit_price <= 0. |
Línea N: descripción es requerida | Descripción vacía. |
Nombre del sujeto excluido es requerido | subject.name vacío. |
Número de documento del sujeto es requerido | subject.document_no vacío. |
Dirección del sujeto es requerida | subject.address vacío. |
Tipo de documento inválido (02, 03, 13, 36, 37) | subject.document_type fuera del rango permitido. |
Departamento/municipio no encontrado: X/Y | Combinación inválida en catálogo MH. |
Anulación
Se anula con un endpoint dedicado que NO comparte ruta con facturas:
curl -X POST https://ocote.io/api/connect/invalidate/suex/SUEX-2026-0015 \
-H "Authorization: Bearer odt_xxx"
Ver Anular DTE.
Ver también
- Wildcard items > Retención Renta 10% — detalle del cálculo automático.
- Consultar estado — endpoint para ver montos calculados y estado MH.
- Anular DTE — incluye la ruta específica para SUEX.
- Catálogos MH — códigos de departamento y municipio.