#El problema: facturar desde código en España es un dolor
Si desarrollas un SaaS, un marketplace o cualquier producto que necesite emitir facturas en España, ya sabes lo que viene: normativa VeriFactu, firma electrónica, encadenamiento criptográfico, código QR verificable, envío a la AEAT. Todo eso además de la lógica de tu producto.
La opción clásica es montar una integración HTTP a mano: construir payloads JSON, gestionar errores, implementar reintentos, manejar idempotencia. Semanas de trabajo que no aportan valor a tu producto.
Publicamos el SDK oficial de BeeL para Node.js precisamente para eliminar esa fricción. Una sola dependencia, tipado completo, y toda la complejidad de la facturación española resuelta en llamadas a métodos.
ℹ️¿Qué es BeeL?
BeeL es un software de facturación para autónomos y empresas en España con cumplimiento VeriFactu. La API pública permite crear, emitir y gestionar facturas programáticamente.
#Instalación y primer cliente
npm install @beel_es/sdkUna sola dependencia (openapi-fetch). Sin frameworks pesados, sin configuración.
import { BeeL } from '@beel_es/sdk';
const beel = new BeeL({ apiKey: process.env.BEEL_API_KEY! });El cliente es instance-based: sin estado global, perfecto para serverless (Vercel, AWS Lambda) y aplicaciones multi-tenant donde cada cliente tiene su propia API key.
// Multi-tenant: un cliente por empresa
const clientEmpresaA = new BeeL({ apiKey: 'beel_sk_live_empresa_a' });
const clientEmpresaB = new BeeL({ apiKey: 'beel_sk_live_empresa_b' });#Crear y emitir una factura
El ciclo de vida completo de una factura: borrador → emitida → pagada.
#Paso 1: Crear el borrador
const invoice = await beel.invoices.create({
type: 'STANDARD',
recipient: { customer_id: 'uuid-del-cliente' },
lines: [
{
description: 'Desarrollo web — Sprint 3',
quantity: 1,
unit_price: 2500,
discount_percentage: 0,
},
{
description: 'Hosting y mantenimiento mensual',
quantity: 1,
unit_price: 150,
discount_percentage: 10,
},
],
});
console.log(invoice.id); // UUID asignado inmediatamente#Paso 2: Emitir (número + VeriFactu)
const issued = await beel.invoices.issue(invoice.id);
console.log(issued.invoice_number); // "A-2026/0042"
console.log(issued.status); // "ISSUED"
// VeriFactu: firma electrónica, QR y registro en AEAT — automáticoAl emitir, BeeL asigna el número correlativo, genera la firma electrónica (CSF), el código QR verificable y registra el documento en la AEAT. Todo transparente para tu código.
#Paso 3: Marcar como pagada y enviar por email
await beel.invoices.markPaid(invoice.id, {
payment_date: '2026-04-09',
});
await beel.invoices.sendEmail(invoice.id, {
to: ['cliente@empresa.com'],
subject: 'Factura A-2026/0042',
message: 'Adjuntamos tu factura. Gracias por confiar en nosotros.',
});#Fluent builders para objetos complejos
Cuando las facturas tienen muchas líneas o los clientes tienen direcciones completas, los builders hacen el código más legible que pasar objetos anidados:
import { InvoiceBuilder, CustomerBuilder } from '@beel_es/sdk';
// Crear cliente con builder
const customerData = CustomerBuilder.create()
.name('Acme SL')
.nif('B12345678')
.email('admin@acme.es')
.phone('+34600123456')
.address('Calle Mayor', '1', '28001', 'Madrid', 'Madrid', 'Spain')
.build();
const customer = await beel.customers.create(customerData);
// Crear factura con builder
const invoiceData = InvoiceBuilder.create()
.forCustomer(customer.id)
.addLine('Consultoría estratégica', 10, 120, 0)
.addLine('Informe ejecutivo', 1, 500, 5)
.dueDate('2026-05-15')
.notes('Pago a 30 días')
.metadata({ proyecto: 'Q2-2026', crm_deal_id: 'deal_789' })
.build();
const invoice = await beel.invoices.create(invoiceData);Los builders validan los campos obligatorios en tiempo de ejecución y convierten objetos Date a ISO strings automáticamente.
Errores tipados: adiós a if (error.status === 422)
El SDK lanza errores específicos en lugar de devolver códigos HTTP genéricos:
import { BeeLValidationError, BeeLNotFoundError, BeeLRateLimitError } from '@beel_es/sdk';
try {
await beel.invoices.create(invoiceData);
} catch (error) {
if (error instanceof BeeLValidationError) {
// error.details → { "lines[0].unit_price": "must be positive" }
console.error('Validación:', error.details);
} else if (error instanceof BeeLNotFoundError) {
console.error('Cliente no encontrado');
} else if (error instanceof BeeLRateLimitError) {
console.error(`Rate limit. Reintentar en ${error.retryAfterSeconds}s`);
}
}| Error | Código HTTP | Cuándo |
|---|---|---|
BeeLAuthError | 401/403 | API key inválida o sin permisos |
BeeLValidationError | 422 | Datos de entrada inválidos |
BeeLNotFoundError | 404 | Recurso no existe |
BeeLConflictError | 409 | Conflicto (ej: factura ya emitida) |
BeeLRateLimitError | 429 | Límite de peticiones excedido |
BeeLApiError | 5xx | Error del servidor |
#Reintentos automáticos e idempotencia
No necesitas implementar lógica de reintentos. El SDK lo hace por ti:
- Reintentos con backoff exponencial en errores 429 y 5xx (3 intentos, delay 500ms → 1s → 2s con jitter)
- Nunca reintenta errores 4xx (son errores del cliente, no transitorios)
- Claves de idempotencia automáticas en cada POST — si un reintento llega dos veces, BeeL descarta el duplicado
Esto significa que puedes llamar a beel.invoices.create() con confianza: si hay un error de red transitorio, el SDK reintenta. Si el reintento llega duplicado, la idempotencia lo descarta. Nunca vas a crear una factura duplicada por un error de red.
#Descargar PDFs
const { download_url, file_name } = await beel.invoices.getPdf(invoice.id);
// download_url es una URL pre-firmada que expira en 5 minutos#Operaciones avanzadas del ciclo de vida
// Duplicar una factura
const copy = await beel.invoices.duplicate(invoiceId);
// Anular una factura emitida
await beel.invoices.void(invoiceId, {
reason: 'Error en los datos del cliente — factura duplicada',
});
// Crear factura rectificativa
const corrective = await beel.invoices.createCorrective(invoiceId, {
type: 'CORRECTIVE',
lines: [{ description: 'Corrección precio', quantity: 1, unit_price: -200, discount_percentage: 0 }],
});
// Programar emisión futura
await beel.invoices.schedule(invoiceId, {
scheduled_for: '2026-05-01',
});#Recursos disponibles
El SDK expone 6 recursos con tipado completo:
| Recurso | Operaciones principales |
|---|---|
beel.invoices | Crear, emitir, pagar, anular, duplicar, PDF, email |
beel.customers | CRUD completo + búsqueda |
beel.products | CRUD completo + búsqueda |
beel.nif | Validar NIF/CIF contra la AEAT |
beel.series | Listar series de facturación |
beel.configuration | Impuestos, idioma, VeriFactu |
#Preguntas frecuentes
#¿El SDK funciona con CommonJS y ESM?
Sí. Se distribuye en formato dual: ESM (import) y CommonJS (require). Funciona en cualquier proyecto Node.js 18+.
#¿Necesito gestionar los reintentos manualmente?
No. El SDK incluye reintentos automáticos con backoff exponencial para errores 429 y 5xx. Los errores 4xx nunca se reintentan porque son errores del cliente.
#¿Cuántas dependencias tiene?
Una: openapi-fetch. El SDK pesa ~123KB y está diseñado para ser lo más ligero posible.
#¿Puedo usar el SDK en un entorno serverless?
Sí. El cliente es instance-based (sin estado global), lo que lo hace perfecto para AWS Lambda, Vercel Functions, Cloudflare Workers o cualquier entorno serverless.
#¿Hay un entorno de pruebas?
Sí. Las API keys con prefijo beel_sk_test_ apuntan al sandbox, donde puedes crear facturas sin consumir cuota VeriFactu.
¿Listo para empezar? Instala el SDK desde npm, consulta el código fuente en GitHub, crea tu cuenta gratuita y emite tu primera factura en minutos. La documentación completa incluye ejemplos para cada operación, y en la página de SDKs tienes quickstarts para TypeScript, Java y Python.
