Saltar al contenido principal

Factura (01)

La Factura (tipo 01) se emite a consumidor final — personas naturales sin NRC, o clientes que no requieren crédito fiscal. Es el tipo de DTE más común en retail, restaurantes y servicios al público.

Detalles técnicos

MétodoPOST
URLhttps://ocote.io/api/connect/invoice
Content-Typeapplication/json
AutenticaciónHeader Authorization: Bearer odt_...

Request

Campos principales

CampoTipoRequeridoDescripción
doc_typestringNo (default "01")Tipo de DTE. Para Factura: "01".
linesarrayLíneas del documento. Al menos una. Ver LineIn.
customerobjectNoDatos del cliente. Opcional en Factura 01. Ver CustomerIn.
customer_namestringNoNombre del consumidor para facturas sin objeto customer. Default: "Consumidor Final".
payment_methodstringNo (default "01")Forma de pago. Ver Catálogos MH.
transaction_conditionintNo (default 1)1 = Contado, 2 = Crédito, 3 = Otro.
deadlineintNo (default 1)Unidad del plazo de crédito (CAT-018 MH): 1 = Días, 2 = Meses, 3 = Años. Solo aplica a transaction_condition: 2.
periodintNo (default 1)Cantidad numérica del plazo. Ej: deadline: 1, period: 30 = 30 días; deadline: 2, period: 2 = 2 meses. Solo aplica a transaction_condition: 2.
activity_codestringNoCódigo de actividad económica del emisor para este documento. Override del default de la empresa.
redirect_emailstringNoCorreo adicional al que se envía copia del DTE (además del del customer).
external_refstringNoTu identificador idempotente. Ver Retry e idempotencia.

Líneas (lines)

CampoTipoRequeridoDescripción
descriptionstringDescripción del producto/servicio. Máx 1 000 caracteres.
quantityfloatCantidad. Debe ser mayor a cero.
unit_pricefloatPrecio unitario con IVA incluido. Debe ser mayor a cero.
discount_percentagefloatNo (default 0)Descuento en porcentaje (0-99).

Cliente (customer)

Totalmente opcional en Factura 01. Si no lo envías o lo envías incompleto, Ocote aplica defaults razonables:

CampoTipoRequeridoDefault (al crear)Descripción
namestring (si envías customer)Nombre o razón social.
nitstringNoNIT del cliente (si aplica).
nrcstringNoNRC del cliente (solo si es contribuyente IVA).
duistringNoDUI para personas naturales.
document_typestringNo"37"Tipo de documento identificador MH.
type_contributorintNo1 (Pequeño)Tipo de contribuyente. Ver Convenciones.
favorite_docstringNo"01"Tipo de DTE preferido del cliente.
addressstringNo"San Salvador"Dirección.
activity_codestringNoCódigo actividad económica del cliente.
districtstringNoUUID del distrito — búscalo en /catalogs/districts/search. Si lo envías, department y municipality se ignoran. Es el flujo recomendado porque no tenés que manejar códigos MH.
departmentstringNoCódigo de departamento MH. Ver Catálogos MH. Si lo envías, municipality también es obligatorio. Ignorado si viene district.
municipalitystringNoCódigo de municipio MH. Acepta formato corto ("24") o largo ("1124") — ver Catálogos MH. Ignorado si viene district.
emailstringNoCorreo electrónico para envío del DTE.
phonestringNoTeléfono.
Clientes nuevos vs existentes

Si el customer.nit (o customer.dui) ya existe en tu empresa en Ocote, el API actualiza únicamente los campos que enviaste explícitamente. Si no existe, crea el cliente con los defaults de la tabla anterior. Los campos fiscales sensibles (type_contributor, favorite_doc, document_type, nit, nrc, dui) se auditan en el log interno de Ocote cuando cambian.

Response

Ver Respuestas y estados para la semántica completa de flags. Campos específicos de /invoice:

CampoTipoDescripción
document_idstring (UUID)Identificador interno Ocote.
external_refstringEl que enviaste (o el autogenerado).
control_numberstringCorrelativo DTE MH. Nunca se regenera.
generation_codestringCódigo de generación MH (igual al UUID en mayúsculas).
reception_stampstringSello de recepción MH. Vacío si contingency: true o rejected: true.
amount_taxablefloatBase gravable (precio sin IVA).
amount_vatfloatIVA 13%.
amount_grossfloatTotal con IVA, antes de retención.
amount_retentionfloatRetención IVA 1% (aplica solo si receptor es type_contributor 3 o 4 y amount_taxable >= 100).
amount_totalfloatTotal neto = amount_gross − amount_retention.
ticket_urlstringURL al ticket PDF térmico (8×21 cm). Disponible si el documento se procesó (is_dte: true). Solo aplica a Factura 01.
invoice_urlstringURL al PDF carta del documento. Solo si dte_success: true.
json_urlstringURL al JSON firmado. Solo si dte_success: true.
dteobjectSchema completo del DTE firmado (solo si dte_success: true).

Ejemplo mínimo: venta simple

curl
curl -X POST https://ocote.io/api/connect/invoice \
-H "Authorization: Bearer odt_xxx" \
-H "Content-Type: application/json" \
-d '{
"external_ref": "VENTA-2026-0042",
"lines": [
{ "description": "Café americano", "quantity": 2, "unit_price": 2.50 },
{ "description": "Empanada de pollo", "quantity": 1, "unit_price": 3.00 }
]
}'
Node.js (axios)
const { data } = await axios.post(
'https://ocote.io/api/connect/invoice',
{
external_ref: 'VENTA-2026-0042',
lines: [
{ description: 'Café americano', quantity: 2, unit_price: 2.50 },
{ description: 'Empanada de pollo', quantity: 1, unit_price: 3.00 },
],
},
{ headers: { Authorization: `Bearer ${process.env.OCOTE_API_KEY}` } }
);
Python (requests)
r = requests.post(
"https://ocote.io/api/connect/invoice",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"external_ref": "VENTA-2026-0042",
"lines": [
{"description": "Café americano", "quantity": 2, "unit_price": 2.50},
{"description": "Empanada de pollo", "quantity": 1, "unit_price": 3.00},
],
},
)

Ejemplo completo: con cliente y crédito

curl
curl -X POST https://ocote.io/api/connect/invoice \
-H "Authorization: Bearer odt_xxx" \
-H "Content-Type: application/json" \
-d '{
"external_ref": "VENTA-2026-0043",
"customer": {
"name": "Juan Pérez",
"dui": "01234567-8",
"email": "juan@example.com",
"phone": "2222-3333",
"address": "Colonia Escalón, San Salvador"
},
"lines": [
{
"description": "Consultoría de marketing - 8 horas",
"quantity": 8,
"unit_price": 50.00,
"discount_percentage": 10
}
],
"payment_method": "05",
"transaction_condition": 2,
"deadline": 1,
"period": 30,
"redirect_email": "contabilidad@miempresa.com"
}'

payment_method: "05" = Transferencia. transaction_condition: 2 = Crédito. deadline: 1, period: 30 = 30 días de crédito. Ver Catálogos MH para el listado completo de códigos.

Respuesta exitosa

{
"success": true,
"dte_success": true,
"contingency": false,
"rejected": false,
"posted": true,
"is_duplicate": false,

"document_id": "a1b2c3d4-1234-5678-9abc-def012345678",
"external_ref": "VENTA-2026-0042",
"control_number": "DTE-01-M001P001-000000000000123",
"generation_code": "A1B2C3D4-1234-5678-9ABC-DEF012345678",
"reception_stamp": "20260421154532...",

"amount_taxable": 7.96,
"amount_vat": 1.04,
"amount_gross": 9.00,
"amount_retention": 0.00,
"amount_total": 9.00,

"ticket_url": "https://ocote.io/api/connect/file/a1b2c3d4-1234-5678-9abc-def012345678?type=ticket",
"invoice_url": "https://ocote.io/api/connect/file/a1b2c3d4-1234-5678-9abc-def012345678?type=invoice",
"json_url": "https://ocote.io/api/connect/file/a1b2c3d4-1234-5678-9abc-def012345678?type=json"
}

Errores de validación específicos

HTTP 400 con detalle en detail:

MensajeCausa
doc_type debe ser uno de: 01, 03, 11Valor de doc_type inválido.
Debe incluir al menos una línealines vacío o ausente.
Línea N: cantidad debe ser mayor a ceroAlgún item con quantity <= 0.
Línea N: precio unitario debe ser mayor a ceroAlgún item con unit_price <= 0.
Línea N: descripción es requeridaDescripción vacía.
Departamento/municipio no encontrado: X/YCombinación department/municipality no existe en el catálogo MH.

Ver también

  • Convenciones — montos con IVA incluido, timezone, valores enumerados.
  • CCF (03) — emisión a contribuyentes IVA con NIT y NRC.
  • Wildcard items — cómo funciona el catálogo interno y retenciones automáticas.
  • Catálogos MH — códigos de actividad, departamento, municipio, forma de pago.
  • Respuestas y estados — semántica completa del response.