La API REST de Timbrify te permite integrar facturación electrónica CFDI 4.0 en cualquier sistema. Todas las peticiones van a https://api.timbrify.com/v1 y devuelven JSON.
https://sandbox.timbrify.com/v1 para probar sin generar CFDIs reales. Las API Keys de sandbox empiezan con tbf_test_.
# npm npm install @timbrify/sdk # yarn yarn add @timbrify/sdk # Python pip install timbrify
Timbrify usa API Keys en el header Authorization: Bearer <key>. Genera tus keys desde el panel de tu comercio en Configuración → API Keys.
// TypeScript / Node.js const response = await fetch('https://api.timbrify.com/v1/invoices', { headers: { 'Authorization': `Bearer ${process.env.TIMBRIFY_API_KEY}`, 'Content-Type': 'application/json', }, });
Genera y timbra un Comprobante Fiscal Digital por Internet (CFDI) versión 4.0. El CFDI queda sellado por el PAC y listo para uso fiscal de forma instantánea.
| Parámetro | Tipo | Req. | Descripción |
|---|---|---|---|
| emisor | object | Sí | Datos del emisor: rfc, nombre, regimenFiscal |
| receptor | object | Sí | Datos del receptor: rfc, nombre, usoCfdi, regimenFiscalReceptor, domicilioFiscal |
| conceptos | array | Sí | Arreglo de conceptos. Cada uno con descripcion, cantidad, valorUnitario, claveProdServ, claveUnidad |
| serie | string | No | Serie de la factura (default: "A") |
| formaPago | string | No | Clave SAT de forma de pago (ej: "03" = transferencia, "04" = tarjeta) |
| metodoPago | string | No | "PUE" (pago en una sola exhibición) o "PPD" (parcialidades) |
| sendEmail | boolean | No | Enviar CFDI al email del receptor (default: true) |
await client.invoices.stamp({ emisor: { rfc: 'PMS901231L84', nombre: 'PEMEX TRANSFORMACION INDUSTRIAL', regimenFiscal: '601', // General de Ley }, receptor: { rfc: 'GOML8902154P3', nombre: 'LAURA GOMEZ MENDOZA', usoCfdi: 'G03', // Gastos en general regimenFiscalReceptor: '605', domicilioFiscal: '06600', // CP }, conceptos: [{ descripcion: 'Gasolina Magna', cantidad: 24.6, valorUnitario: 17.16, claveProdServ: '15101514', claveUnidad: 'LTR', impuestos: { traslados: [{ base: 422.14, impuesto: '002', // IVA tipoFactor: 'Tasa', tasaOCuota: '0.160000', importe: 67.54, }], }, }], formaPago: '04', // Tarjeta de crédito metodoPago: 'PUE', });
{
"success": true,
"invoice": {
"id": "inv_01HPQR2X4Y7Z",
"uuid": "A4F2E918-3D1C-4B2A-9E87-F1234567890A",
"folio": "TBF-00482",
"serie": "A",
"status": "stamped",
"total": 489.68,
"subtotal": 422.14,
"iva": 67.54,
"pac": "facturama",
"stamped_at": "2026-02-23T10:30:00.000Z",
"pdf_url": "https://cdn.timbrify.com/pdf/A4F2E918.pdf",
"xml_url": "https://cdn.timbrify.com/xml/A4F2E918.xml"
}
}
Timbrify usa códigos HTTP estándar. Los errores devuelven un objeto JSON con code y message descriptivos.
| Código HTTP | Código interno | Descripción |
|---|---|---|
| 200 | — | Operación exitosa |
| 400 | INVALID_RFC | El RFC del receptor no existe o está cancelado en el SAT |
| 400 | INVALID_CFDI | Error en la estructura del XML (parámetros inválidos) |
| 401 | UNAUTHORIZED | API Key inválida o expirada |
| 402 | QUOTA_EXCEEDED | Límite mensual de CFDIs alcanzado. Considera upgradear tu plan |
| 429 | RATE_LIMITED | Demasiadas peticiones. Ver Rate limits |
| 503 | PAC_UNAVAILABLE | Ambos PACs no disponibles (rarísimo). Reintentar en 30s |
Timbrify envía eventos HTTP POST a tu endpoint cuando ocurren cambios en facturas. Todos los webhooks incluyen firma HMAC-SHA256 para verificación.
| Evento | Descripción |
|---|---|
| invoice.stamped | CFDI timbrado exitosamente |
| invoice.cancelled | CFDI cancelado en el SAT |
| invoice.email_sent | Email enviado al receptor |
| invoice.complement_generated | Complemento de pago (REP) generado |
| qr.scanned | QR ticket escaneado por consumidor |
import { createHmac } from 'crypto'; export function verifyWebhook(payload: string, signature: string, secret: string) { const expected = createHmac('sha256', secret) .update(payload) .digest('hex'); return `sha256=${expected}` === signature; } // En tu endpoint Fastify / Express: const isValid = verifyWebhook( req.rawBody, req.headers['x-timbrify-signature'], process.env.TIMBRIFY_WEBHOOK_SECRET );