Facturar
Emitir una factura desde tu sistema
Con la API de facturación de Timbro, tu sistema de caja o tu ERP sigue registrando la venta y Timbro emite la factura electrónica ante la DGII. Puedes emitir antes o después de cobrar, y el cliente puede pagar con Timbro, en efectivo, por transferencia o en tu terminal de tarjeta. Facturar no requiere una afiliación.
Para emitir necesitas la facturación configurada y una clave de API con acceso a Facturación, que en estos ejemplos guardas en TIMBRO_INVOICES_API_KEY. La clave determina el negocio y el modo, Prueba o En vivo, así que tus solicitudes no los indican.
Instala el SDK en tu servidor:
npm install @timbro/invoicesEl SDK de Python necesita Python 3.11 o posterior.
pip install timbro-invoicesEmite la factura
Sección titulada «Emite la factura»Envía los datos fiscales reales de la venta. Este ejemplo emite una Factura de Consumo pagada al contado:
import { createTimbroInvoices } from "@timbro/invoices";
const timbro = createTimbroInvoices({ apiKey: process.env.TIMBRO_INVOICES_API_KEY! });const invoice = await timbro.invoices.create({ invoiceReference: "venta-842-factura", type: "E32", currency: "DOP", incomeType: "01", paymentTerms: { type: "immediate" }, items: [{ description: "Servicio", quantity: "1", unit: "unit", kind: "service", unitPrice: "1250.00", tax: { kind: "itbis_18", included: true }, }],});TimbroInvoices es el cliente síncrono. Si tu servidor usa asyncio, AsyncTimbroInvoices tiene los mismos métodos con await. Las solicitudes y respuestas son diccionarios con los nombres de campo de la API.
import os
from timbro_invoices import TimbroInvoices
timbro = TimbroInvoices(api_key=os.environ["TIMBRO_INVOICES_API_KEY"])invoice = timbro.invoices.create({ "invoiceReference": "venta-842-factura", "type": "E32", "currency": "DOP", "incomeType": "01", "paymentTerms": {"type": "immediate"}, "items": [{ "description": "Servicio", "quantity": "1", "unit": "unit", "kind": "service", "unitPrice": "1250.00", "tax": {"kind": "itbis_18", "included": True}, }],})| Campo | Qué indica |
|---|---|
invoiceReference |
El identificador de esta factura en tu sistema. Debe ser único por negocio y modo |
type |
El tipo de e-CF: E31, E32, E33, E34, E41, E43, E44, E45, E46 o E47 |
incomeType |
El tipo de ingreso de la DGII. 01 son ingresos por operaciones no financieras. Si no lo envías, Timbro usa el del perfil del negocio |
paymentTerms |
Si el cliente pagó al contado, compró a crédito o la venta es gratuita |
items |
Cada artículo con su cantidad, unidad de medida, precio e impuesto. Los montos son texto con punto decimal |
Cada tipo pide datos distintos, y el esquema InvoiceRequest de la referencia REST los detalla. No inventes datos para completar una solicitud.
Usar HTTP directamente
Guarda el mismo cuerpo en invoice.json y envíalo desde tu servidor:
curl --request POST 'https://api.timbro.do/v1/invoices' \ --header "Authorization: Bearer $TIMBRO_INVOICES_API_KEY" \ --header 'Content-Type: application/json' \ --data-binary @invoice.jsonEvita emitir dos facturas por la misma venta
Sección titulada «Evita emitir dos facturas por la misma venta»invoiceReference identifica la factura. Si repites la solicitud con la misma referencia y los mismos datos, Timbro devuelve la misma factura en vez de emitir otra. Por eso, guarda la solicitud en tu sistema antes de enviarla, y si pierdes la respuesta, repítela tal como estaba, sin cambiar sus datos. Una referencia nueva pide otra factura.
Si tu sistema envía las facturas desde una cola de trabajo, busca primero la referencia y solo emite si no existe:
const found = await timbro.invoices.list({ invoiceReference: "venta-842-factura" });found = timbro.invoices.list(invoice_reference="venta-842-factura")Para guardar en la factura el documento de tu sistema que la originó, envía source: { id, version }, por ejemplo el ID del documento y su número de versión. Si tu sistema tiene que volver a facturar una venta, por ejemplo después de un rechazo, envía el mismo id con una version nueva y una invoiceReference nueva.
Indica cómo pagó el cliente
Sección titulada «Indica cómo pagó el cliente»paymentTerms describe el pago tal como debe aparecer en la factura:
{ "type": "immediate" }para una venta al contado. Si quieres que la factura muestre cómo pagó el cliente, añadeallocationscon una entrada por forma de pago, hasta 7. Cada forma de pago (method) escash,bank_transfer,card,credit_sale,gift_certificate,barter,credit_noteuother. Indica los montos en pesos dominicanos; deben sumar el total de la factura.{ "type": "credit", "dueOn": "2026-11-30" }para una venta a crédito, con la fecha en que vence.{ "type": "free" }para una venta gratuita. La DGII no acepta este caso en los tipos E31, E33, E34 y E45.
Por ejemplo, una venta de RD$ 1,250.00 pagada en parte en efectivo y en parte con tarjeta:
{ "type": "immediate", "allocations": [ { "method": "cash", "amount": "500.00" }, { "method": "card", "amount": "750.00" } ]}Puedes cobrar una factura a crédito en abonos con Timbro, como explica Cobra una factura en abonos.
Identifica al comprador
Sección titulada «Identifica al comprador»- Una Factura de Crédito Fiscal (
E31) necesita enbuyerel RNC o la cédula del comprador (taxId) y su nombre o razón social (legalName). - Una Factura de Consumo (
E32) de menos de RD$ 250,000.00 puede no tener comprador. Desde ese monto, la DGII exige identificar al comprador. Si el cliente te dio sus datos, envíalos enbuyer. - Un Comprobante Gubernamental (
E45) necesita, además del comprador,governmentEligibilitycon el tipo de entidad.
Para un comprador extranjero, envía kind: "foreign" con su identificación en foreignId.
Comprueba los totales de tu sistema
Sección titulada «Comprueba los totales de tu sistema»Timbro calcula los totales con las reglas de redondeo de la DGII. Si tu sistema ya calculó los totales de la venta, envíalos en expectedTotals con net, tax, total y nonBillable. Si no coinciden al centavo con los de Timbro, Timbro rechaza la factura en vez de emitir otros montos, así tu contabilidad y el e-CF nunca difieren.
Para revisar los datos y los totales sin emitir, usa invoices.preview con la misma solicitud. La vista previa no asigna un e-NCF ni envía nada a la DGII.
Factura en otra moneda
Sección titulada «Factura en otra moneda»Para facturar en dólares o en euros, envía currency y la tasa de cambio en exchangeRate.rate: cuántos pesos dominicanos vale una unidad de esa moneda, con hasta 4 decimales. La tasa de referencia de la DGII para una fecha está en GET /v1/exchange-rates/USD?date=2026-10-21. Para euros, cambia USD por EUR.
La Factura de Consumo (E32) y las notas que la modifican se emiten solo en pesos dominicanos. Una venta con propina legal o con cargos no facturables también se emite en pesos. Timbro siempre cobra en pesos dominicanos.
Imprime la factura en tu caja
Sección titulada «Imprime la factura en tu caja»Para imprimir la factura en una impresora de recibos, envía pdfLayout: "receipt80mm"; el PDF tendrá 80 mm de ancho. Si no lo envías, el PDF usa el tamaño A4.
Si tu sistema imprime la factura con su propio formato, lee fiscalIdentity.signature cuando la DGII la acepte. Trae la fecha de firma (signedAt), el código de seguridad (securityCode) y el link del QR (verificationUrl) que debe mostrar la factura impresa. Es null mientras Timbro no haya firmado el e-CF.
Consulta el estado
Sección titulada «Consulta el estado»La respuesta trae el id de la factura, su e-NCF cuando se asigna, y su status:
| Estado | Qué significa |
|---|---|
processing, verifying |
Timbro la envió a la DGII y espera su respuesta. Consulta más tarde |
accepted |
La DGII la aceptó |
acceptedWithObservations |
La DGII la aceptó con observaciones que debes revisar |
rejected |
Timbro la rechazó antes de enviarla a la DGII. Corrige los datos y emite otra |
authorityRejected |
La DGII la rechazó. Puedes reemplazarla |
operatorRequired |
Necesita que el equipo de Timbro la revise |
closed |
Una persona administradora del negocio la cerró antes de que llegara a la DGII. Puedes reemplazarla |
Consulta la factura por su id. Los webhooks invoice.accepted e invoice.rejected te avisan cuando cambia:
const current = await timbro.invoices.retrieve(invoice.id);if (!current) throw new Error("Invoice not found");const isAccepted = current.status === "accepted" || current.status === "acceptedWithObservations";invoices.retrieve lanza NotFoundError cuando la factura no existe.
current = timbro.invoices.retrieve(invoice["id"])is_accepted = current["status"] in ("accepted", "acceptedWithObservations")La aceptación de la DGII no significa que el XML y el PDF estén listos. Para descargarlos o enviarlos al cliente, sigue Descargar y enviar la factura. Para cobrar la factura con Timbro, sigue Cobrar una factura que ya emitiste.
Emitir la factura no registra un asiento contable ni confirma un pago. Tu sistema sigue llevando la contabilidad de la venta.