Desarrolladores · API v1 · versión 2026-10-21
API de Trevol
Emite facturas electrónicas y notas crédito y débito ante la DIAN desde tu propio software. Tú mandas los datos; Trevol valida, calcula los impuestos y totales, numera, firma, envía a la DIAN y entrega el PDF y el correo.
1. Cómo empezar
- Crea tu cuenta y tu empresa en app.trevol.si y termina su habilitación ante la DIAN (Trevol la hace por ti).
- Crea una llave de pruebas en la app: Integraciones → API → Nueva llave, ambiente Pruebas. La llave (
tvl_test_…) se muestra una sola vez. - Emite tu primera factura contra la habilitación real de la DIAN: sin validez legal y sin costo.
curl https://api.trevol.si/v1/company -H "Authorization: Bearer $TREVOL_LLAVE"
Cuando tu integración funcione, crea una llave de producción (tvl_live_…): emite con la resolución de numeración de la empresa y cada documento validado se descuenta de tu saldo.
2. Llaves y seguridad
Cada llave es de una sola empresa y un solo ambiente. La empresa sale de la llave, nunca del pedido: si tienes varias empresas, cada una tiene sus llaves, y una llave nunca puede emitir ni consultar documentos de otra.
Authorization: Bearer tvl_test_…(habilitación de la DIAN) otvl_live_…(producción).- Permisos: «Emitir y consultar» o «Solo consultar».
- IP permitidas (opcional): hasta 10 direcciones o redes; la llave solo sirve desde ellas.
- Solo el titular de la cuenta crea o revoca llaves, y cada vez le avisamos por correo. Revocar es inmediato.
- Guarda la llave como un secreto en tu servidor: nunca en una página web ni en una app de celular. Trevol solo guarda su huella (sha256).
3. Convenciones
- Dirección:
https://api.trevol.si/v1. JSON en UTF-8; campos en inglés y mensajes en español. - Montos: en los pedidos, número o texto decimal con punto (
"150000.50"); en las respuestas, siempre texto con 2 decimales. Las cantidades admiten hasta 6 decimales. - Precios sin impuestos:
unit_priceva antes de IVA; Trevol calcula impuestos, retenciones y totales. - Códigos de la DIAN como texto:
"01","31","47". - Identificadores con prefijo:
inv_factura,cn_nota crédito,dn_nota débito. - Fechas ISO 8601;
issued_aten hora de Bogotá (-05:00). - Un campo desconocido es un error: no se ignora en silencio.
Trevol-Version: 2026-10-21(opcional) yRequest-Iden cada respuesta.
4. Emitir una factura
Es síncrono: en la misma petición Trevol valida, numera, firma, envía a la DIAN y espera su respuesta.
curl https://api.trevol.si/v1/invoices \
-H "Authorization: Bearer $TREVOL_LLAVE" \
-H "Idempotency-Key: 6f1c2a7e-0b3d-4c2a-9d0e-1a2b3c4d5e6f" \
-H "Content-Type: application/json" \
-d '{
"external_id": "ERP-2026-000123",
"customer": {
"document_type": "31", "document_number": "900373913", "name": "FICORP SAS",
"person_type": "legal", "email": "facturas@ficorp.co", "municipality_code": "76001",
"tax_responsibilities": ["O-13"]
},
"items": [{
"code": "SA-LIC", "description": "Licencia anual", "quantity": "1", "unit_price": "150000",
"taxes": [{"code": "01", "rate": "19"}]
}],
"payment": {"form": "credit", "term_days": 30, "methods": [{"code": "47"}]}
}'
HTTP/1.1 201 Created
Location: /v1/invoices/inv_08cd6774e31e401c9fa0fbf92b3fbdc0
Request-Id: req_8f0bd4b74c070af09ae4e620
{
"id": "inv_08cd6774e31e401c9fa0fbf92b3fbdc0",
"object": "invoice",
"environment": "test",
"status": "accepted",
"number": "SETP994307051",
"prefix": "SETP",
"external_id": "ERP-2026-000123",
"cufe": "52cede538652…",
"qr": "NumFac: SETP994307051 …",
"issued_at": "2026-10-21T22:09:36-05:00",
"customer": { … },
"items": [ … ],
"totals": {
"subtotal": "150000.00", "discounts": "0.00", "line_extension": "150000.00",
"taxes": [{"code": "01", "name": "IVA", "rate": "19.00", "base": "150000.00", "amount": "28500.00"}],
"total": "178500.00", …
},
"dian": {"status_code": "00", "message": "Procesado Correctamente.", "rules": []},
"delivery": {"pdf": true, "zip": true, "xml": true, "email": {"status": "sent", "to": "facturas@ficorp.co"}}
}
Para consumidor final: "customer": {"final_consumer": true}. Para calcular sin emitir: POST /v1/invoices/preview con el mismo cuerpo (no numera ni pide Idempotency-Key).
La fase 1 cubre la factura de venta nacional con todo lo del Anexo técnico 1.9 (impuestos porcentuales y nominales, descuentos y recargos, retenciones, muestras gratis, anticipos, redondeo) y las notas crédito y débito. Exportación, moneda extranjera, documento soporte, POS, nómina y eventos RADIAN llegan en las fases siguientes.
5. Estados y respuestas
| HTTP | Qué pasó |
|---|---|
| 201 | La DIAN validó el documento (status: accepted). |
| 422 dian_rejected | La DIAN lo rechazó; document trae el documento y sus reglas traducidas. |
| 422 validation_error | Trevol lo rechazó antes de numerar: no se gastó nada. |
| 402 insufficient_balance | Producción sin saldo: queda pending con su número. |
| 503 dian_unavailable | La DIAN no contestó: reintenta con la misma Idempotency-Key. |
status: pending (numerado, sin enviar) · sending · accepted · rejected · error (no se pudo enviar) · contingency. Todos los errores: catálogo de errores.
6. Idempotencia
Idempotency-Keyes obligatoria al crear o corregir un documento: un UUID nuevo por documento.- Repetir la misma clave con el mismo cuerpo (durante 7 días) devuelve la misma respuesta con
Idempotent-Replayed: true, sin volver a emitir. - La misma clave con otro cuerpo es idempotency_key_reused: nunca te devolvemos otro documento en silencio.
- Si la primera petición no terminó (402, 503), el reintento con la misma clave sigue con el mismo documento y el mismo número.
external_id(opcional): tu identificador; repetido es external_id_in_use con el id del que ya existe.
7. Rechazos, reintentos y notas
- Rechazado por la DIAN: corrige con
PUT /v1/invoices/{id}(cuerpo completo, nueva Idempotency-Key). Sale con el mismo número. Un rechazo no bloquea los demás envíos. - Pendiente o en error:
POST /v1/invoices/{id}/sendlo vuelve a enviar (por ejemplo, después de recargar saldo). - Validado: ya no se cambia; se corrige con una nota crédito o débito.
curl https://api.trevol.si/v1/credit_notes \
-H "Authorization: Bearer $TREVOL_LLAVE" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"invoice": {"id": "inv_08cd6774e31e401c9fa0fbf92b3fbdc0"},
"concept": "1",
"description": "Devolución parcial",
"items": [{"description": "Devolución de una licencia", "quantity": "1", "unit_price": "50000",
"taxes": [{"code": "01", "rate": "19"}]}]
}'
Con una factura de Trevol, la nota usa su cliente si no envías customer. Trevol revisa antes de numerar que la nota crédito no pase del saldo de la factura. Conceptos: NC 1–6, ND 1–4 (tabla de la DIAN).
8. Consultar, listar y archivos
GET /v1/invoices/{id}: el documento.GET /v1/invoices?limit=20&starting_after=inv_…: lista por cursor (tambiénstatus,external_id,created_from,created_to).GET /v1/invoices/{id}/pdf,/xml,/zipy/dian_response: los archivos en binario, listos para guardar.GET /v1/dian/acquirer?document_type=31&document_number=…: lo que la DIAN tiene del adquiriente (nombre y correo).
9. Límites
Por llave: 120 envíos por minuto, 20.000 al día y 600 consultas por minuto; por empresa, 50.000 envíos al día entre todas sus llaves. Al pasarse: rate_limited con Retry-After.
10. Rutas
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /v1/health | Salud |
| GET | /v1/company | La empresa de la llave |
| GET | /v1/dian/acquirer | Datos del adquiriente en la DIAN |
| POST | /v1/invoices | Emitir una factura |
| GET | /v1/invoices | Listar (factura) |
| POST | /v1/invoices/preview | Calcular una factura sin emitirla |
| GET | /v1/invoices/{id} | Una factura |
| PUT | /v1/invoices/{id} | Corregir una factura rechazada (mismo número) y reenviarla |
| POST | /v1/invoices/{id}/send | Reenviar una pendiente o en error |
| GET | /v1/invoices/{id}/pdf | Archivo pdf |
| GET | /v1/invoices/{id}/xml | Archivo xml |
| GET | /v1/invoices/{id}/zip | Archivo zip |
| GET | /v1/invoices/{id}/dian_response | Archivo dian_response |
| POST | /v1/credit_notes | Emitir una nota crédito |
| GET | /v1/credit_notes | Listar (nota crédito) |
| POST | /v1/credit_notes/preview | Calcular una nota crédito sin emitirla |
| GET | /v1/credit_notes/{id} | Una nota crédito |
| PUT | /v1/credit_notes/{id} | Corregir una nota crédito rechazada (mismo número) y reenviarla |
| POST | /v1/credit_notes/{id}/send | Reenviar una pendiente o en error |
| GET | /v1/credit_notes/{id}/pdf | Archivo pdf |
| GET | /v1/credit_notes/{id}/xml | Archivo xml |
| GET | /v1/credit_notes/{id}/zip | Archivo zip |
| GET | /v1/credit_notes/{id}/dian_response | Archivo dian_response |
| POST | /v1/debit_notes | Emitir una nota débito |
| GET | /v1/debit_notes | Listar (nota débito) |
| POST | /v1/debit_notes/preview | Calcular una nota débito sin emitirla |
| GET | /v1/debit_notes/{id} | Una nota débito |
| PUT | /v1/debit_notes/{id} | Corregir una nota débito rechazada (mismo número) y reenviarla |
| POST | /v1/debit_notes/{id}/send | Reenviar una pendiente o en error |
| GET | /v1/debit_notes/{id}/pdf | Archivo pdf |
| GET | /v1/debit_notes/{id}/xml | Archivo xml |
| GET | /v1/debit_notes/{id}/zip | Archivo zip |
| GET | /v1/debit_notes/{id}/dian_response | Archivo dian_response |
11. Campos
Generados de la especificación OpenAPI.
Factura (cuerpo de POST y PUT /v1/invoices)
| Campo | Tipo | Qué es |
|---|---|---|
external_id | texto | Tu identificador del documento: único entre los documentos API de la empresa y el ambiente. |
customer | Customer | |
items obligatorio | lista de Item | Las líneas (1 a 500). Máximo 500. |
payment | Payment | |
notes | lista de texto | Máximo 10. |
period | Period | |
references | References | |
allowance_charges | lista de AllowanceCharge | Descuentos y recargos globales (no tocan las bases). Máximo 20. |
prepayments | lista de Prepayment | Anticipos (informativos: no restan del total). Máximo 20. |
withholdings | lista de Withholding | Retenciones (informativas): 05 ReteIVA, 06 ReteRenta, 07 ReteICA. Máximo 10. |
rounding | booleano o decimal | true = redondeo al peso; o un valor entre -2.00 y 2.00. |
Cliente (customer)
| Campo | Tipo | Qué es |
|---|---|---|
final_consumer | booleano | |
document_type | texto | Tipo de documento (tabla 13.2.1 de la DIAN): 13 CC, 31 NIT, 22 CE, 41 PA… |
document_number | texto | Sin DV ni puntos; el DV lo calcula Trevol. |
check_digit | entero | Opcional: si viene, tiene que ser el DV del NIT. |
name | texto | |
person_type | legal | natural | Por defecto se deduce del NIT. |
email | texto | |
phone | texto | |
address | texto | |
city | texto | |
municipality_code | texto | Código DANE del municipio (5 dígitos). |
department_code | texto | |
tax_responsibilities | lista de texto | Tabla 13.2.6.1 (O-13, O-15, O-23, O-47, R-99-PN). Máximo 20. |
tax_scheme | texto | TaxScheme del adquiriente: 01, 04, ZA o ZZ (por defecto ZZ). |
Línea (items[])
| Campo | Tipo | Qué es |
|---|---|---|
code | texto | Código (texto). |
description obligatorio | texto | |
unit | texto | Unidad de medida (tabla 13.3.6). Por defecto 94 (unidad). |
quantity obligatorio | decimal | Número o texto decimal con punto («150000.50»). |
unit_price obligatorio | decimal | Precio unitario SIN impuestos. |
taxes | lista de ItemTax | Impuestos de la línea: {code, rate} porcentual, {code: "01", excluded: true} o nominal {code, unit_amount, unit?, quantity?}. Máximo 12. |
discounts | lista de ItemAllowance | Máximo 10. |
charges | lista de ItemAllowance | Máximo 10. |
withholdings | lista de ItemWithholding | Retenciones (informativas): 05 ReteIVA, 06 ReteRenta, 07 ReteICA. Máximo 10. |
free_of_charge | FreeOfCharge | |
standard_code | StandardCode | |
brand | texto | |
model | texto |
Impuesto de la línea (items[].taxes[])
| Campo | Tipo | Qué es |
|---|---|---|
code obligatorio | texto | Código (texto). |
rate | decimal | Tarifa en % (ICA y ReteICA: por mil). |
excluded | booleano | |
unit_amount | decimal | Número o texto decimal con punto («150000.50»). |
unit | texto | Unidad de medida (tabla 13.3.6). Por defecto 94 (unidad). |
quantity | decimal | Número o texto decimal con punto («150000.50»). |
volume_cc | decimal | Número o texto decimal con punto («150000.50»). |
name | texto |
Descuento o recargo de la línea
| Campo | Tipo | Qué es |
|---|---|---|
code | texto | Código (texto). |
reason | texto | |
percent | decimal | Número o texto decimal con punto («150000.50»). |
amount | decimal | Número o texto decimal con punto («150000.50»). |
Retención de la línea
| Campo | Tipo | Qué es |
|---|---|---|
code obligatorio | texto | Código (texto). |
rate obligatorio | decimal | Tarifa en % (ICA y ReteICA: por mil). |
self_withholding | booleano |
Muestra gratis
| Campo | Tipo | Qué es |
|---|---|---|
reference_price | decimal | Número o texto decimal con punto («150000.50»). |
price_type | texto |
Identificación estándar del artículo
| Campo | Tipo | Qué es |
|---|---|---|
scheme | texto | |
value | texto |
Pago (payment)
| Campo | Tipo | Qué es |
|---|---|---|
form obligatorio | cash | credit | cash (contado) | credit (crédito: con due_date o term_days). |
term_days | entero | |
due_date | fecha (AAAA-MM-DD) | |
methods | lista de PaymentMethod | Medios de pago (tabla 13.3.4.2): 10 efectivo, 42 consignación, 47 transferencia… Máximo 5. |
Medio de pago
| Campo | Tipo | Qué es |
|---|---|---|
code obligatorio | texto | Código (texto). |
reference | texto |
Periodo
| Campo | Tipo | Qué es |
|---|---|---|
start | fecha (AAAA-MM-DD) | |
end | fecha (AAAA-MM-DD) |
Referencias
| Campo | Tipo | Qué es |
|---|---|---|
purchase_order | DocumentReference | |
despatches | lista de DocumentReference | Máximo 20. |
receipts | lista de DocumentReference | Máximo 20. |
Documento referenciado
| Campo | Tipo | Qué es |
|---|---|---|
id | texto | |
date | fecha (AAAA-MM-DD) |
Descuento o recargo global
| Campo | Tipo | Qué es |
|---|---|---|
type obligatorio | discount | charge | |
code | texto | Código (texto). |
reason | texto | |
percent | decimal | Número o texto decimal con punto («150000.50»). |
amount | decimal | Número o texto decimal con punto («150000.50»). |
base | decimal | Número o texto decimal con punto («150000.50»). |
Anticipo
| Campo | Tipo | Qué es |
|---|---|---|
id obligatorio | texto | |
amount obligatorio | decimal | Número o texto decimal con punto («150000.50»). |
received_date obligatorio | fecha (AAAA-MM-DD) | |
paid_date | fecha (AAAA-MM-DD) | |
instructions | texto |
Retención del documento
| Campo | Tipo | Qué es |
|---|---|---|
code obligatorio | texto | Código (texto). |
rate obligatorio | decimal | Tarifa en % (ICA y ReteICA: por mil). |
self_withholding | booleano | |
base | decimal | Número o texto decimal con punto («150000.50»). |
Nota crédito o débito (cuerpo)
| Campo | Tipo | Qué es |
|---|---|---|
external_id | texto | Tu identificador del documento: único entre los documentos API de la empresa y el ambiente. |
customer | Customer | |
items obligatorio | lista de Item | Las líneas (1 a 500). Máximo 500. |
payment | Payment | |
notes | lista de texto | Máximo 10. |
period | Period | |
references | References | |
allowance_charges | lista de AllowanceCharge | Descuentos y recargos globales (no tocan las bases). Máximo 20. |
prepayments | lista de Prepayment | Anticipos (informativos: no restan del total). Máximo 20. |
withholdings | lista de Withholding | Retenciones (informativas): 05 ReteIVA, 06 ReteRenta, 07 ReteICA. Máximo 10. |
rounding | booleano o decimal | true = redondeo al peso; o un valor entre -2.00 y 2.00. |
concept obligatorio | texto | Concepto de corrección: NC 1–6, ND 1–4. |
description | texto | |
invoice | InvoiceReference |