Excluded Subject — SUEX (14)
The Excluded Subject DTE (type 14) is a document issued by the buyer, not the seller. It's used when your company buys from a natural person who is not a VAT contributor (no NRC) — typically professional services, rentals, purchases from small producers, etc.
Unlike Invoice 01 and CCF 03 where the flow is "I sell and I issue", in SUEX the flow is "I buy and I document the purchase" — hence it uses the PurchaseHeader model internally, not SalesHeader.
SUEX stands for "Sujeto Excluido", the Spanish term used in Salvadoran fiscal terminology.
When to use SUEX
- Payments to independent professionals without NRC.
- Purchases from individual suppliers not registered for VAT.
- Rentals to individuals.
- Any purchase from a "Sujeto Excluido" in MH fiscal terms.
Automatic 10% income-tax withholding
When a line is flagged is_service: true, the API automatically applies a 10% withholding on the service value as income-tax advance. Your company pays this withholding to MH monthly; the excluded subject receives the net amount (total − withholding).
If the line is is_service: false (purchase of goods), no income-tax withholding applies.
Technical details
| Method | POST |
| URL | https://ocote.io/api/connect/suex |
| Content-Type | application/json |
| Authentication | Header Authorization: Bearer odt_... |
Request
Main fields
| Field | Type | Required | Description |
|---|---|---|---|
lines | array | Yes | Document lines. At least one. |
subject | object | Yes | Data of the excluded subject (seller). |
external_ref | string | No | Your idempotent identifier. |
Lines (lines)
| Field | Type | Required | Description |
|---|---|---|---|
description | string | Yes | Good/service description. Max 1,000 characters. |
quantity | float | Yes | Quantity. Must be greater than zero. |
unit_price | float | Yes | Unit price. Must be greater than zero. |
is_service | bool | No (default false) | true → applies 10% income-tax withholding. |
Subject (subject)
All fields describe the excluded subject (the seller you're buying from).
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Full name of the subject. |
document_type | string | No (default "13") | Identifier document type. Valid values: "02" (Resident Card), "03" (Passport), "13" (DUI), "36" (NIT), "37" (Other). |
document_no | string | Yes | Identifier document number. |
address | string | Yes | Subject's address. |
department | string | No | MH department code. If you send it, municipality is also required. |
municipality | string | No | MH municipality code. |
phone_number | string | No | Phone. Unlike customer.phone in Invoice/CCF, this field works correctly. |
email | string | No | Email address. |
If you issue a SUEX with a document_no that already exists in your company, Ocote updates the subject's data (address, email, etc.) and reuses the record. This avoids duplicates in your subjects database.
Response
Structure identical to /invoice with the same state flags (success, dte_success, contingency, rejected, etc.). See Responses and states.
Unlike /invoice, the direct response of POST /suex does not include the computed amount fields. To get amount, amount_irs (income-tax withholding), and total_pay (net amount to pay), query the document state with GET /suex/status/{id_or_ref} after issuing. See Query status.
Example: payment for professional services
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": "Corporate legal consulting - March 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: 'Corporate legal consulting - March 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": "Corporate legal consulting - March 2026",
"quantity": 1,
"unit_price": 1500.00,
"is_service": True,
},
],
},
)
Querying the computed amounts
After issuing, query the status to see the applied withholding:
curl https://ocote.io/api/connect/suex/status/SUEX-2026-0015 \
-H "Authorization: Bearer odt_xxx"
Response:
{
"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": ""
}
Breakdown:
amount: 1500.00— declared service value.amount_irs: 150.00— 10% income-tax withholding (1500 × 0.10). Paid by your company to MH.total_pay: 1350.00— the amount you actually transfer to Ana María.
Example without withholding: purchase of goods
If you buy goods (not services), flag 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": "White corn - 10 quintals",
"quantity": 10,
"unit_price": 45.00,
"is_service": false
}
]
}
In the status response we'll see amount_irs: 0.00 and total_pay: 450.00.
Specific validation errors
HTTP 400 with detail populated:
| Message | Cause |
|---|---|
Debe incluir al menos una línea | lines empty or absent. |
Línea N: cantidad debe ser mayor a cero | Some item has quantity <= 0. |
Línea N: precio unitario debe ser mayor a cero | Some item has unit_price <= 0. |
Línea N: descripción es requerida | Empty description. |
Nombre del sujeto excluido es requerido | subject.name empty. |
Número de documento del sujeto es requerido | subject.document_no empty. |
Dirección del sujeto es requerida | subject.address empty. |
Tipo de documento inválido (02, 03, 13, 36, 37) | subject.document_type out of allowed range. |
Departamento/municipio no encontrado: X/Y | Invalid combination in MH catalog. |
Messages are in Spanish — the language MH operates in.
Invalidation
Invalidation uses a dedicated endpoint that does NOT share the route with invoices:
curl -X POST https://ocote.io/api/connect/invalidate/suex/SUEX-2026-0015 \
-H "Authorization: Bearer odt_xxx"
See Invalidate DTE.
See also
- Wildcard items > 10% income-tax withholding — automatic calculation detail.
- Query status — endpoint to see computed amounts and MH state.
- Invalidate DTE — includes the SUEX-specific route.
- MH catalogs — department and municipality codes.