Si tu sistema ya sabe qué se vendió, a quién y por cuánto, no tiene sentido que una persona vuelva a escribirlo en otra pantalla. Peor todavía desde enero de 2026, cuando los comprobantes se transmiten al SRI de inmediato y ese trabajo manual tiene que ocurrir en el mostrador, con la cola esperando.
Esta guía es para quien va a escribir la integración: qué pide la API de Timbre, qué devuelve y cuáles son las tres o cuatro decisiones que conviene no equivocar.
Cuándo conviene integrar
No siempre. Si emites diez facturas al mes, el panel es más rápido que cualquier integración. La API se paga sola cuando:
- Tu punto de venta o tu ERP ya registra la venta completa.
- Alguien está copiando datos de un sistema a otro todos los días.
- Facturas desde varias cajas o varios locales a la vez.
- Vendes en línea y el comprobante debe salir al confirmarse el pago.
Los tres conceptos que hay que tener claros
1. La credencial de máquina
No se integra con el usuario y la contraseña de una persona. Se crea una credencial de API desde el panel, en Credenciales de API, y queda un token con esta forma:
tmb_<identificador>_<secreto>
El secreto se muestra una sola vez, al crearla. No se puede volver a ver, ni desde el panel ni desde administración: si se pierde, se revoca y se emite otra.
Cada credencial pertenece a una empresa y nunca cruza a otra. Revocarla corta el acceso de inmediato y el registro queda, con la fecha de último uso.
2. El ambiente lo decide la credencial
Cada credencial apunta a pruebas o a producción, y eso determina el ambiente de los comprobantes que crea. No depende del ambiente activo de la empresa ni de un campo del cuerpo.
Esto es a propósito: puedes tener la llave de sandbox y la llave real
funcionando al mismo tiempo, y tu entorno de desarrollo nunca va a emitir un
comprobante real por un if mal puesto. Las secuencias también son
independientes, así que probar no consume números de producción.
Crear una credencial de producción exige que el correo del usuario esté verificado.
3. La URL es la de tu empresa
Cada empresa vive en su propio subdominio, y el Host es lo que identifica de
qué empresa son los datos:
https://tuempresa.timbre.devarech.com
Emitir una factura
Una sola llamada. Este es el cuerpo completo:
POST /api/documents/
Authorization: Bearer tmb_xxxxxxxxxxxx_...
Content-Type: application/json
Idempotency-Key: venta-4471
{
"customer": {
"identification_type": "05",
"identification": "0954469045",
"legal_name": "LOPEZ MALDONADO MARLENE",
"email": "cliente@example.com",
"address": "MILAGRO"
},
"document_type": "01",
"establishment_code": "001",
"emission_point_code": "001",
"issue_date": "2026-09-17",
"lines": [
{
"product": {
"code": "CAFE",
"name": "Café americano",
"product_type": "good",
"unit_price": "2.50",
"iva_code": "4",
"iva_rate": "15"
},
"quantity": "2",
"unit_price": "2.50",
"discount": "0.00"
}
],
"payments": [
{ "payment_method": "01", "amount": "5.75" }
]
}
identification_type sigue la tabla del SRI: 04 RUC, 05 cédula, 06
pasaporte. document_type es 01 para factura y 04 para nota de crédito.
No hace falta dar de alta nada antes
Este es el detalle que ahorra la mitad del trabajo. customer y el product
de cada línea aceptan el identificador de una fila existente o el objeto
entero. Mandas la venta completa y el servidor resuelve: lo que no existe se
crea, lo que ya existía se actualiza. La identificación es la clave del cliente
y el código es la clave del producto.
Sin eso, integrar significa un paso previo por cada cliente nuevo y por cada producto nuevo, o mantener en tu base una tabla de equivalencias entre tus identificadores y los nuestros. No hay que hacer ninguna de las dos cosas.
La creación ocurre dentro de la misma transacción que el comprobante: si la emisión falla, no queda un cliente suelto de una factura que nunca existió.
Los totales los calcula el servidor
Mandas cantidades, precios y descuentos. Subtotales, IVA, ICE, IRBPNR y total los calcula el backend, sin importar por qué canal entró la venta. Si tu sistema calcula el IVA por su cuenta y no coincide, la fuente de verdad es la que va al SRI.
Idempotencia: la cabecera que evita la factura duplicada
Idempotency-Key es un identificador tuyo de la venta: el número de pedido,
el id de la transacción, lo que uses internamente. Hasta 64 caracteres.
Sirve para el caso que siempre pasa: mandas la petición, se corta la red, no
sabes si llegó. Reintentas con la misma clave y la API devuelve el documento
original con 200 y la cabecera Idempotent-Replay: true, en lugar de emitir
una segunda factura y quemar otro secuencial.
HTTP/1.1 200 OK
Idempotent-Replay: true
Si dos peticiones con la misma clave llegan a la vez, una gana y la otra reproduce el documento de la ganadora. No hay forma de terminar con dos comprobantes para una venta.
Úsala siempre. Es una línea de código y es la diferencia entre un reintento seguro y una nota de crédito.
La autorización no llega en la respuesta
Cuando el POST responde, el comprobante está guardado y enviado, pero el SRI
puede tardar en resolverlo. No lo sondees: configura un webhook.
Se registra en /api/webhooks/ con una URL https tuya, y llega esto cuando el
SRI resuelve:
{
"event": "document.authorized",
"status": "authorized",
"reference": "venta-4471",
"document_id": "3f8a1c2e-5b74-4d61-9a03-27d5e9f1b840",
"formatted_number": "001-001-000000015",
"access_key": "0409202601179001234500110010010000000151234567814",
"authorization_number": "0409202601179001234500110010010000000151234567814",
"authorized_at": "2026-09-17T15:21:08-05:00",
"environment": "test",
"grand_total": "11.50",
"message": ""
}
Dos cosas que importan:
referencees tuIdempotency-Key. Es lo que te permite reconocer de qué venta te están hablando sin guardar nuestros identificadores.environmentviene en el aviso. Hay un solo webhook para los dos ambientes; quien lo recibe decide qué hacer con cada uno.
El aviso lleva un token opcional que viaja como Authorization: Bearer, para
que puedas verificar que el POST vino de nosotros. Se reintenta cinco veces con
espera creciente ante un 5xx, un 429 o una caída; un 4xx no se repite, porque si
tu servidor dice que el cuerpo está mal, repetirlo no lo va a arreglar.
Para no configurarlo a ciegas, POST /api/webhooks/{id}/probar/ manda un aviso
de prueba.
Si prefieres consultar, GET /api/documents/{id}/ devuelve el estado actual.
Los errores vienen donde viajó el dato
Un 400 no trae un mensaje suelto: trae los errores anidados en la misma forma
que mandaste, con la lista de líneas alineada con la tuya.
{
"customer": {
"identification": ["La cédula ingresada no es válida."]
},
"lines": [
{},
{
"product": {
"iva_code": ["Selecciona una tarifa IVA activa del catálogo compartido."]
}
}
]
}
La segunda línea es la que tiene el problema. Puedes marcar el campo exacto en tu interfaz sin adivinar.
Distingue los tres fracasos
No son lo mismo y la acción que corresponde tampoco:
| Qué pasó | Cómo se ve | Qué haces |
|---|---|---|
| Tu cuerpo está mal | 400 con los campos |
Corriges y reenvías |
| El SRI devolvió el comprobante | El documento existe, con su motivo | Corriges el dato y reintentas; conservas el número |
| El SRI no respondió | El documento existe, en error temporal | Reintentas el envío, no vuelvas a crear el documento |
El tercero es el que más duele cuando se maneja mal. El comprobante ya tiene su clave de acceso; volver a crearlo desde cero quema un secuencial y puede dejarte con dos facturas para una venta. Lo explicamos con detalle en los estados de una factura electrónica.
También puedes recibir un 400 diciendo que se acabó el cupo de comprobantes
del mes de tu plan. Vale la pena tratarlo aparte en tu código: no es un error
del dato, es una señal de que hay que cambiar de plan.
Antes de pasar a producción
- La integración funciona de punta a punta con una credencial de pruebas.
- Todas las emisiones mandan
Idempotency-Key. - Un corte de red en medio de la emisión no produce dos comprobantes. Pruébalo.
- El webhook está registrado, verificado con
/probar/y responde2xx. - Tu sistema guarda el
access_keyde cada comprobante. - El correo del usuario dueño de la credencial está verificado.
- Establecimiento, punto de emisión y secuencia existen para el ambiente de producción, que es independiente del de pruebas.
- El token está en una variable de entorno y no en el repositorio.
- Tienes una credencial por integración, no una compartida entre todas.
Lo que todavía no hay
Para que decidas con la información completa:
- No hay versionado de rutas. Las rutas van planas, sin
/v1/. Avisamos antes de cualquier cambio incompatible, pero es algo que debes saber. - No hay esquema OpenAPI publicado. La referencia vive en el panel, con ejemplos en JavaScript, TypeScript, Python, C# y Postman.
- No hay cuota por credencial distinta de la del plan.
Timbre expone esta API desde el panel, en Credenciales de API, con los ejemplos en tu lenguaje y el dominio de tu empresa ya puestos. Ver planes o empezar por la guía de facturación paso a paso.
Este contenido describe el comportamiento de la API de Timbre. Las obligaciones tributarias deben contrastarse con la normativa vigente del SRI.