Ejemplos por caso
Facturas completas y listas para copiar, con los casos que más aparecen y los que el sandbox todavía no admite.
Cada ejemplo de esta página es un cuerpo completo de POST /v1/invoices, comprobado contra el contrato en cada compilación de este sitio. Cámbiale el numbering_range_id por el tuyo y funciona.
Lo que aquí no aparece es porque el sandbox todavía no lo admite: retenciones, anticipos y monedas distintas del peso. Ver Catálogos y códigos.
Venta a consumidor final
El caso más común en un restaurante o una tienda: el cliente no da ningún dato. La DIAN reserva para eso la identificación 222222222222, y Cufy la emite validada.
El comprador es siempre el mismo, sin dirección y sin correo:
| Campo | Valor | Por qué |
|---|---|---|
party_type | "final_consumer" | Es lo que activa el perfil. |
identification.type_code | "13" | Lo fija la DIAN. |
identification.number | "222222222222" | El número reservado. No se admite con otro party_type, ni otro número con este. |
name | "Consumidor final" | |
tax_registration.responsibility_codes | ["R-99-PN"] | Única responsabilidad admitida. |
tax_registration.tax_scheme_codes | ["ZZ"] | "No aplica". No es 01: el consumidor final no declara IVA. |
Si algo no cuadra, la respuesta trae BUYER_FINAL_CONSUMER_PROFILE y el campo exacto. Sin correo llega el aviso BUYER_EMAIL_MISSING, que no impide emitir.
{
"document_type": "invoice",
"external_reference": "CONSUMIDOR-FINAL-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T13:00:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "final_consumer",
"identification": { "type_code": "13", "number": "222222222222" },
"name": "Consumidor final",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["ZZ"]
}
},
"lines": [
{
"id": "1",
"description": "Almuerzo del día",
"product_identification": { "scheme_code": "999", "value": "MENU-001" },
"quantity": "1",
"unit_code": "94",
"unit_price": "20000.00",
"price_base_quantity": "1",
"net_amount": "20000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "20000.00", "amount": "3800.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "19", "taxable_amount": "20000.00", "amount": "3800.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "20000.00",
"tax_exclusive_amount": "20000.00",
"tax_inclusive_amount": "23800.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "23800.00"
},
"payment": { "terms": "cash", "means_code": "10" }
}Una factura así se corrige como cualquier otra: la nota conserva exactamente el mismo comprador. En el sandbox ya hay una factura a consumidor final anulada por nota crédito, las dos validadas por la DIAN.
Venta de mostrador identificada
Cuando el cliente sí da su cédula, envíalo como un comprador person normal.
Un comprador person no necesita dirección, y el correo es opcional: si no lo envías, la respuesta trae el aviso BUYER_EMAIL_MISSING y la factura sigue siendo válida.
{
"document_type": "invoice",
"external_reference": "MOSTRADOR-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T10:00:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "person",
"identification": { "type_code": "13", "number": "1020304050" },
"name": "Cliente de mostrador",
"email": "cliente@example.com",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["01"]
}
},
"lines": [
{
"id": "1",
"description": "Producto de mostrador",
"product_identification": { "scheme_code": "999", "value": "PROD-001" },
"quantity": "1",
"unit_code": "94",
"unit_price": "10000.00",
"price_base_quantity": "1",
"net_amount": "10000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "10000.00", "amount": "1900.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "19", "taxable_amount": "10000.00", "amount": "1900.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "10000.00",
"tax_exclusive_amount": "10000.00",
"tax_inclusive_amount": "11900.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "11900.00"
},
"payment": { "terms": "cash", "means_code": "10" }
}Si el comprador es una empresa, cambian tres cosas: party_type pasa a company, la identificación tiene que ser NIT (31) con su check_digit, y la dirección deja de ser opcional. El ejemplo siguiente la incluye.
Venta a crédito
Con terms: "credit", due_date es obligatorio. Es una fecha sola, YYYY-MM-DD, sin hora ni zona.
El vencimiento se compara con la fecha colombiana
due_date no puede ser anterior a la fecha de issued_at convertida a hora de Colombia. El mismo día sí vale. Si emites a las 2026-09-21T02:00:00Z, en Colombia todavía es 20 de septiembre, y 2026-09-20 es un vencimiento válido.
{
"document_type": "invoice",
"external_reference": "CREDITO-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T10:00:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "company",
"identification": { "type_code": "31", "number": "900123456", "check_digit": "1" },
"name": "Distribuidora Ejemplo SAS",
"email": "facturacion@example.com",
"address": {
"country_code": "CO",
"department_code": "11",
"municipality_code": "11001",
"city_name": "Bogotá, D.C.",
"line": "Calle 100 # 10-20"
},
"tax_registration": {
"responsibility_codes": ["O-13"],
"tax_scheme_codes": ["01"]
}
},
"lines": [
{
"id": "1",
"description": "Servicio mensual de soporte",
"product_identification": { "scheme_code": "999", "value": "SOP-001" },
"quantity": "1",
"unit_code": "94",
"unit_price": "500000.00",
"price_base_quantity": "1",
"net_amount": "500000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "500000.00", "amount": "95000.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "19", "taxable_amount": "500000.00", "amount": "95000.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "500000.00",
"tax_exclusive_amount": "500000.00",
"tax_inclusive_amount": "595000.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "595000.00"
},
"payment": {
"terms": "credit",
"means_code": "10",
"due_date": "2026-10-20",
"reference": "OC-2026-4471"
}
}No hay plazo máximo: due_date puede ser tan lejano como quieras.
Restaurante: impoconsumo e IVA en la misma cuenta
En un restaurante la comida paga impoconsumo (04, 8 %) y algunas bebidas, IVA (01, 19 %). Van en la misma factura, cada renglón con su impuesto, y tax_totals trae un bloque por cada uno.
- Un renglón lleva un solo impuesto. No se suman IVA e impoconsumo sobre la misma línea.
- El impoconsumo solo admite la tarifa
8. tax_inclusive_amountes la base más los dos impuestos: 52.000 + 3.200 + 2.280 = 57.480.
Esta cuenta, a consumidor final y pagada con efectivo y tarjeta, es la que la DIAN validó en el sandbox.
{
"document_type": "invoice",
"external_reference": "MESA-12-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T13:30:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "final_consumer",
"identification": { "type_code": "13", "number": "222222222222" },
"name": "Consumidor final",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["ZZ"]
}
},
"lines": [
{
"id": "1",
"description": "Bandeja paisa",
"product_identification": { "scheme_code": "999", "value": "PLATO-001" },
"quantity": "2",
"unit_code": "94",
"unit_price": "20000.00",
"price_base_quantity": "1",
"net_amount": "40000.00",
"adjustments": [],
"taxes": [
{ "code": "04", "rate": "8", "taxable_amount": "40000.00", "amount": "3200.00" }
],
"withholdings": []
},
{
"id": "2",
"description": "Gaseosa",
"product_identification": { "scheme_code": "999", "value": "BEBIDA-001" },
"quantity": "2",
"unit_code": "94",
"unit_price": "6000.00",
"price_base_quantity": "1",
"net_amount": "12000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "12000.00", "amount": "2280.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "19", "taxable_amount": "12000.00", "amount": "2280.00" },
{ "code": "04", "rate": "8", "taxable_amount": "40000.00", "amount": "3200.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "52000.00",
"tax_exclusive_amount": "52000.00",
"tax_inclusive_amount": "57480.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "57480.00"
},
"payment": {
"terms": "cash",
"means": [
{ "code": "10", "amount": "30000.00" },
{ "code": "48", "amount": "27480.00" }
]
}
}Precio de menú con el impuesto incluido
La carta dice $15.000 y ese es el precio con impoconsumo. La factura no lleva ese número en el precio, lleva la base, así que se saca el impuesto:
- Base: el precio dividido entre 1,08 y redondeado a centavos. 15.000 ÷ 1,08 = 13.888,89.
- Impuesto: lo que falta para llegar al precio. 15.000 − 13.888,89 = 1.111,11.
- Total: vuelve a dar exactamente 15.000.
La cuenta exacta del impuesto sería 13.888,89 × 8 % = 1.111,1112. Cufy acepta el impuesto de cada renglón hasta un peso por encima o por debajo de esa cuenta. La DIAN compara ese valor redondeado al peso (regla FAX07) y admite una holgura de ±2 pesos en los importes (anexo técnico, §5.2.1.1). En tax_totals y en los totales va la suma de lo que declaraste en los renglones, sin tolerancia adicional.
{
"document_type": "invoice",
"external_reference": "MESA-7-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-24T13:10:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "final_consumer",
"identification": { "type_code": "13", "number": "222222222222" },
"name": "Consumidor final",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["ZZ"]
}
},
"lines": [
{
"id": "1",
"description": "Bandeja del día",
"product_identification": { "scheme_code": "999", "value": "PLATO-002" },
"quantity": "1",
"unit_code": "94",
"unit_price": "13888.89",
"price_base_quantity": "1",
"net_amount": "13888.89",
"adjustments": [],
"taxes": [
{ "code": "04", "rate": "8", "taxable_amount": "13888.89", "amount": "1111.11" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "04", "rate": "8", "taxable_amount": "13888.89", "amount": "1111.11" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "13888.89",
"tax_exclusive_amount": "13888.89",
"tax_inclusive_amount": "15000.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "15000.00"
},
"payment": { "terms": "cash", "means_code": "10" }
}Si pides varias unidades del mismo plato, calcula la base del renglón completo, no la de una unidad: dos bandejas son 30.000 ÷ 1,08 = 27.777,78. unit_price × quantity tiene que dar net_amount, y 13.888,89 × 2 = 27.777,78.
Producto con IVA 0 %
Cero por ciento no es lo mismo que exento
El sandbox no distingue exento de excluido. Esa clasificación vive en un perfil que hoy solo existe en simulación, y enviar vat_treatment aquí se rechaza. Lo que puedes emitir es una línea de IVA (01) con tarifa 0.
Una línea siempre lleva exactamente un impuesto. No existe la línea sin IVA: la que no lo paga lo lleva al 0 %, con su amount en "0.00", y ese bloque de cero también tiene que aparecer en tax_totals.
{
"document_type": "invoice",
"external_reference": "IVA0-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T10:00:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "person",
"identification": { "type_code": "13", "number": "1000000000" },
"name": "Comprador de ejemplo",
"email": "comprador@example.com",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["01"]
}
},
"lines": [
{
"id": "1",
"description": "Producto con IVA 0%",
"product_identification": { "scheme_code": "999", "value": "PROD-IVA0" },
"quantity": "3",
"unit_code": "94",
"unit_price": "20000.00",
"price_base_quantity": "1",
"net_amount": "60000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "0", "taxable_amount": "60000.00", "amount": "0.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "0", "taxable_amount": "60000.00", "amount": "0.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "60000.00",
"tax_exclusive_amount": "60000.00",
"tax_inclusive_amount": "60000.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "60000.00"
},
"payment": { "terms": "cash", "means_code": "10" }
}Varios ítems con tarifas distintas
tax_totals no repite una línea por renglón: lleva una entrada por tarifa, con la suma de las bases y la suma de los impuestos de todas las líneas que la usan.
Aquí hay cuatro renglones (19 %, 5 %, 0 % y otro 19 %) y tres entradas en tax_totals: las dos líneas al 19 % se suman en una sola de 130.000 y 24.700.
| Si haces esto | Recibes |
|---|---|
Repetir una tarifa en tax_totals | DUPLICATE_TAX |
| Poner una tarifa que ninguna línea usa | UNEXPECTED_TAX |
| Olvidar la tarifa de una línea | MISSING_TAX |
El orden de tax_totals no importa.
{
"document_type": "invoice",
"external_reference": "MULTI-001",
"profile_id": "co-sale-cop-v1",
"numbering_range_id": "00000000-0000-4000-8000-000000000010",
"issued_at": "2026-09-20T10:00:00-05:00",
"currency": "COP",
"buyer": {
"party_type": "person",
"identification": { "type_code": "13", "number": "1000000000" },
"name": "Comprador de ejemplo",
"email": "comprador@example.com",
"tax_registration": {
"responsibility_codes": ["R-99-PN"],
"tax_scheme_codes": ["01"]
}
},
"lines": [
{
"id": "1",
"description": "Producto gravado al 19%",
"product_identification": { "scheme_code": "999", "value": "PROD-19" },
"quantity": "2",
"unit_code": "94",
"unit_price": "50000.00",
"price_base_quantity": "1",
"net_amount": "100000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "100000.00", "amount": "19000.00" }
],
"withholdings": []
},
{
"id": "2",
"description": "Producto gravado al 5%",
"product_identification": { "scheme_code": "999", "value": "PROD-05" },
"quantity": "4",
"unit_code": "94",
"unit_price": "15000.00",
"price_base_quantity": "1",
"net_amount": "60000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "5", "taxable_amount": "60000.00", "amount": "3000.00" }
],
"withholdings": []
},
{
"id": "3",
"description": "Producto con IVA 0%",
"product_identification": { "scheme_code": "999", "value": "PROD-00" },
"quantity": "1",
"unit_code": "94",
"unit_price": "25000.00",
"price_base_quantity": "1",
"net_amount": "25000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "0", "taxable_amount": "25000.00", "amount": "0.00" }
],
"withholdings": []
},
{
"id": "4",
"description": "Segundo producto gravado al 19%",
"product_identification": { "scheme_code": "999", "value": "PROD-19B" },
"quantity": "1",
"unit_code": "94",
"unit_price": "30000.00",
"price_base_quantity": "1",
"net_amount": "30000.00",
"adjustments": [],
"taxes": [
{ "code": "01", "rate": "19", "taxable_amount": "30000.00", "amount": "5700.00" }
],
"withholdings": []
}
],
"adjustments": [],
"tax_totals": [
{ "code": "01", "rate": "19", "taxable_amount": "130000.00", "amount": "24700.00" },
{ "code": "01", "rate": "5", "taxable_amount": "60000.00", "amount": "3000.00" },
{ "code": "01", "rate": "0", "taxable_amount": "25000.00", "amount": "0.00" }
],
"withholding_totals": [],
"totals": {
"line_extension_amount": "215000.00",
"tax_exclusive_amount": "215000.00",
"tax_inclusive_amount": "242700.00",
"allowance_total_amount": "0.00",
"charge_total_amount": "0.00",
"prepaid_amount": "0.00",
"payable_rounding_amount": "0.00",
"payable_amount": "242700.00"
},
"payment": { "terms": "cash", "means_code": "10" }
}Con descuento, con cargo, con propina
is_charge decide si el ajuste suma o resta. Un descuento declara además su reason_code —00 no condicionado, 01 condicionado—; un cargo no lo lleva, porque el catálogo de la DIAN solo categoriza descuentos.
El importe se expresa de dos maneras, y son excluyentes:
- Proporcional: con
base_amountypercentage, y entoncesamounttiene que ser exactamentebase_amount × percentage / 100. Es el descuento del 10 % de siempre. - De importe fijo: sin
base_amountnipercentage, yamountse declara tal cual. Es lo que hace falta cuando no hay porcentaje exacto que dé ese número: una propina de $5.000 sobre una cuenta de $43.170.
Declarar solo uno de los dos da ADJUSTMENT_BASE_INCOMPLETE. Un ajuste de importe fijo mayor que aquello que ajusta da ADJUSTMENT_ABOVE_BASE, porque la DIAN lo rechaza.
En una línea, el net_amount se recalcula como cantidad × precio − descuentos + cargos, y ese neto sí es la base del IVA y del impoconsumo. En la cabecera no se toca ninguna base: el ajuste solo mueve el payable_amount.
La propina va ahí: un cargo de cabecera, de importe fijo. Por ser voluntaria no hace parte de la base del impoconsumo (art. 512-9 del Estatuto Tributario), y un cargo de cabecera es justo lo que no entra en ninguna base.
El descuento de cabecera limita la nota crédito
Una factura con descuentos o cargos de cabecera solo se corrige anulándola completa: una nota crédito parcial se rechaza con CREDIT_GLOBAL_ADJUSTMENT_PARTIAL, porque ese descuento no pertenece a ninguna línea y no hay forma de repartirlo. Si prevés notas parciales, pon el descuento en las líneas.
Lo que nunca envías
Ninguno de estos ejemplos lleva emisor, número de factura, CUFE ni firma. Los pone Cufy. El contrato los rechaza si los mandas.