#¿Cómo se integra Verifactu en Node.js?
Para integrar Verifactu en Node.js no necesitas certificados digitales ni XML: se hace a través de una API que actúe como sistema informático de facturación (SIF) certificado. Con BeeL. el flujo es: instalar el SDK@beel_es/sdk, crear una factura conbeel.invoices.create(), emitirla conbeel.invoices.issue()— BeeL. genera el hash encadenado, el QR oficial y la registra en la AEAT — y escuchar el webhookverifactu.status.updatedpara confirmar la aceptación. Todo el proceso, de cero a factura registrada, lleva unos 10 minutos.
Eso es el resumen. Ahora vamos paso a paso, con código TypeScript completo que puedes copiar y pegar, y la respuesta JSON real de cada llamada.
¿Qué es Verifactu?
Verifactu es el sistema de la AEAT (Real Decreto 1007/2023) que obliga a que todo software de facturación en España firme, encadene con hash SHA-256 y registre cada factura en Hacienda. Es obligatorio para sociedades desde el 1 de enero de 2027 y para autónomos desde el 1 de julio de 2027. Si tu aplicación Node.js emite facturas, esto te afecta directamente.
Casi todos los tutoriales de integración Verifactu que existen son para PHP o para conectarte por SOAP directamente contra la AEAT. Esta guía es lo contrario: Node.js + TypeScript, REST y JSON, usando la API de BeeL. como capa de cumplimiento. BeeL. es el SIF; tú solo haces llamadas HTTP.
#Paso 1: Cuenta y API key de sandbox (2 minutos)
- Crea tu cuenta gratuita en app.beel.es
- Ve a Ajustes → API Keys, pulsa Create API Key y selecciona el entorno sandbox (la key solo se muestra una vez)
Las keys de sandbox llevan el prefijo beel_sk_test_. Como explica la documentación de autenticación, ambos entornos comparten la misma base URL pero los datos están aislados:
| Entorno | Prefijo | ¿Envía a la AEAT? |
|---|---|---|
| Sandbox | beel_sk_test_ | No — datos aislados, facturas ilimitadas que no consumen cuota |
| Producción | beel_sk_live_ | Sí — registro Verifactu real, números legalmente vinculantes |
La base URL es siempre la misma: https://app.beel.es/api/v1, con autenticación Authorization: Bearer <tu-api-key>.
Guarda la key en una variable de entorno (nunca en el código):
#Paso 2: Instalar el SDK (1 minuto)
Una sola dependencia (openapi-fetch), tipado completo, ESM + CommonJS, Node 18+. Inicializa el cliente:
El cliente es instance-based (sin estado global), así que funciona igual en un servidor Express que en Vercel o AWS Lambda. Si prefieres REST puro sin SDK, todos los pasos de esta guía tienen su equivalente HTTP en la referencia de la API.
#Paso 3: Crear el cliente al que vas a facturar (2 minutos)
Toda factura estándar necesita un destinatario con NIF y dirección. Créalo una vez y reutiliza su id:
La respuesta REST equivalente (POST /v1/customers) llega siempre en el mismo envelope { success, data, meta }:
#Paso 4: Crear la factura en borrador (2 minutos)
En BeeL. una factura nace como borrador (DRAFT): editable, sin número fiscal y sin registro en la AEAT todavía. Referencia completa: createInvoice.
Respuesta JSON (campos principales):
Dos detalles importantes del modelo:
invoice_numberesnullen borradores. El número correlativo se asigna en la emisión — exactamente lo que exige la normativa antifraude.- El endpoint soporta el header
Idempotency-Key: si tu petición se reintenta por un timeout de red, no se crea una factura duplicada. El SDK genera estas claves automáticamente en cada POST.
#Paso 5: Emitir la factura — aquí ocurre Verifactu (1 minuto)
Emitir (issueInvoice, POST /v1/invoices/{id}/issue) pasa la factura de DRAFT a ISSUED: se asigna el número definitivo, se congela el documento y BeeL. genera el registro Verifactu (hash encadenado + QR) y lo envía a la AEAT. Tu código no cambia nada para que esto pase: es el comportamiento por defecto.
Respuesta JSON con el bloque verifactu incluido:
El submission_status arranca en PENDING: BeeL. ya ha enviado el registro a la AEAT y está esperando el veredicto. Cuando la AEAT acepta, el objeto verifactu se completa con invoice_hash (SHA-256 del registro), chaining_hash (encadenamiento con la factura anterior), registration_number y qr_base64 (el QR como PNG en base64, por si renderizas tus propios PDFs). En sandbox nada viaja a la AEAT real, pero el flujo de estados es el mismo.
No hagas polling
Podrías consultar GET /v1/invoices/{id} en bucle hasta ver ACCEPTED, pero hay una forma mejor: el webhook del paso 7.
#Paso 6: Obtener el QR y el PDF (1 minuto)
El PDF se genera con el QR Verifactu, el hash y la leyenda oficial. Con el SDK lo descargas directamente como Buffer:
Y si prefieres una URL de descarga prefirmada (por ejemplo, para abrirla desde el navegador), el endpoint REST GET /v1/invoices/{id}/pdf (generateInvoicePdf) devuelve una URL temporal que expira en 5 minutos:
Si emites con POST /v1/invoices/{id}/issue?wait_for_pdf=true, la respuesta de emisión ya espera a que el PDF esté generado (~1-2 s extra de latencia). Y si lo que quieres es el QR para incrustarlo en tu propia plantilla, usa verifactu.qr_base64 cuando el registro esté en ACCEPTED.
#Paso 7: Webhook de confirmación de la AEAT (3 minutos)
La AEAT responde de forma asíncrona. Para reaccionar al veredicto en tiempo real, suscríbete al evento verifactu.status.updated:
La respuesta incluye un campo secret (whsec_...) que solo se muestra una vez — guárdalo, lo necesitas para verificar firmas. Después, el handler en Express con el verificador del SDK:
Payload real del evento cuando la AEAT acepta:
Los estados posibles de new_status son PENDING, ACCEPTED, ACCEPTED_WITH_ERRORS, REJECTED y AEAT_SERVER_ERROR (en este último BeeL. reintenta automáticamente, sin que tú toques nada). Detalles a tener en cuenta:
- Tu endpoint debe responder
2xxen menos de 10 segundos; si no, BeeL. reintenta con backoff exponencial hasta un total de 5 intentos (el original + 4 reintentos). - Cada evento llega con el header
BeeL-Event-Id, idéntico en todos los reintentos — úsalo para deduplicar. - Las suscripciones están aisladas por entorno: las de sandbox solo reciben eventos de sandbox (
livemode: false). - ¿Aún no tienes endpoint? Apunta la suscripción a webhook.site y mira los payloads en directo.
#Paso 8: Checklist de paso a producción
Cuando el flujo funcione en sandbox, pasar a producción es una lista corta:
- ✓Sustituye la key beel_sk_test_ por una beel_sk_live_ (misma base URL, mismo código)
- ✓Completa tus datos fiscales y la serie de facturación en el panel de BeeL.
- ✓Crea la suscripción de webhook en producción (las de sandbox no reciben eventos live) y guarda su secret
- ✓Verifica la firma BeeL-Signature en todos los webhooks — nunca proceses un payload sin verificar
- ✓Deduplica eventos por BeeL-Event-Id y responde 2xx en menos de 10 segundos
- ✓Maneja el estado REJECTED: registra error_code y error_message de la AEAT y emite rectificativa si procede
- ✓No reintentes tú los envíos a la AEAT: BeeL. gestiona los reintentos respetando el encadenamiento
- ✓Guarda qr_url e invoice_hash de cada factura aceptada en tu base de datos
Eso es todo. Nada de certificados digitales, ni SOAP, ni esquemas XSD de la AEAT: BeeL. es el sistema informático de facturación certificado (con su declaración responsable publicada) y tu aplicación Node.js solo consume una API REST.
#Preguntas frecuentes
#¿Necesito un certificado digital para integrar Verifactu en Node.js?
No, si usas una API como la de BeeL. El certificado, la firma del registro, el encadenamiento de hashes y la comunicación con la AEAT los gestiona BeeL. como sistema informático de facturación. Tu aplicación solo necesita una API key con autenticación Bearer.
#¿Puedo probar la integración sin enviar nada a la AEAT?
Sí. Las API keys con prefijo beel_sk_test_ operan contra un sandbox aislado: las facturas no se envían a la AEAT, no consumen tu cuota mensual y puedes crear todas las que quieras. Es el entorno pensado para desarrollo y CI/CD.
#¿Qué pasa si la AEAT rechaza una factura?
Recibes un evento verifactu.status.updated con new_status: "REJECTED" y los campos error_code y error_message con el motivo exacto que devuelve la AEAT (por ejemplo, un NIF de emisor no registrado). La factura ya emitida no se borra: se corrige con una factura rectificativa según el caso.
#¿El webhook es obligatorio o puedo consultar el estado por API?
Puedes consultar GET /v1/invoices/{id} y leer verifactu.submission_status, pero el webhook es la forma recomendada: te evita hacer polling y te notifica en tiempo real cada cambio de estado. Los webhooks están disponibles con el plan Developer.
#¿Cuánto se tarda de verdad en integrar Verifactu con esta API?
El flujo de esta guía — cuenta, SDK, cliente, factura, emisión, PDF y webhook — se completa en unos 10 minutos en sandbox. Una integración productiva con manejo de errores y deduplicación de eventos suele cerrarse en una tarde, frente a las semanas/meses que lleva integrarse directamente contra los servicios SOAP de la AEAT.
#¿En qué se diferencia este tutorial del post sobre el SDK de TypeScript?
Este tutorial cubre el flujo Verifactu de punta a punta (registro AEAT, QR, hash, webhook de confirmación y paso a producción). Si quieres profundizar en el SDK en sí — builders, errores tipados, reintentos, idempotencia y el resto de recursos — tienes la guía completa en Facturación automática en Node.js con el SDK de TypeScript.
¿Listo para integrar? Crea tu cuenta gratuita, explora la API pública de BeeL. y la landing de la API Verifactu, o ve directo a la referencia: crear factura, emitir factura, autenticación y eventos de webhook.