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:

  • reference es tu Idempotency-Key. Es lo que te permite reconocer de qué venta te están hablando sin guardar nuestros identificadores.
  • environment viene 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 responde 2xx.
  • Tu sistema guarda el access_key de 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.