# Cómo integrar VeriFactu en un SaaS o software propio con una arquitectura que pueda mantenerse

> Una integración SaaS robusta debe tratar VeriFactu como una capa server-to-server. Define un eventId estable por operación, elige InvoiceIntent directo o MappingProfile, ejecuta preflight y solo después llama a issue con una Idempotency-Key determinista. Persiste recordId en cuanto lo recibas. Si existe recordId, cualquier sync posterior debe consultar ese registro aunque el error anterior fuera retryable; no vuelvas a issue. Mantén API key, certificado, tenant, instalación y entorno fuera del frontend. Para validar un adapter propio, implementa preflight/source, send con eventId, status(recordId) y sync; ejecuta Connector Contract Suite v2 en CI. La suite comprueba el contrato de integración, pero no certifica normativa ni habilita AEAT producción.

Canonical: https://kairoseth.com/es/blog/como-integrar-verifactu-saas-software-propio-contract-suite
Product: [Software VeriFactu](https://kairoseth.com/products/kairoseth-fiscal)
Primary query: cómo integrar VeriFactu en un SaaS
Intent: informational-how-custom-software-saas-verifactu-integration-works
Published: 2026-10-07
Updated: 2026-10-07
Geographic scope: España
Geographic context: La arquitectura descrita puede reutilizarse en otros dominios, pero la aplicación fiscal de este contenido se limita al marco español SIF/VERI*FACTU. El gate de producción revisa AEAT/BOE vigentes en la fecha de activación.

La integración más resistente no copia la normativa dentro del SaaS. Separa hechos comerciales y capa fiscal, utiliza REST o SDK solo desde backend, valida con preflight, conserva identidad con eventId/Idempotency-Key, persiste recordId y reconcilia en vez de reemitir. Connector Contract Suite v2 convierte esas reglas en tests ejecutables para adapters de terceros.

Un equipo de producto suele abordar una integración fiscal como cualquier otra API externa: crea un cliente, envía una factura y espera una respuesta. Esa aproximación es insuficiente cuando la operación tiene identidad durable y un timeout no demuestra que el servidor no haya procesado el registro. También es peligrosa si el cliente termina recibiendo autoridad sobre tenant, certificado o clasificación fiscal solo porque esos conceptos caben en JSON. Puente VeriFactu define un contrato más estricto. El software propio conserva los hechos de negocio; el servidor resuelve organización, instalación, sourceSystem y secretos; preflight separa validación de efectos; Idempotency-Key protege la creación; recordId se convierte en la referencia después de crear; y sync debe reconciliar, nunca volver a emitir como fallback. El SDK server-side reduce boilerplate y Connector Contract Suite v2 permite convertir esos invariantes en un gate CI independiente del framework, ERP o lenguaje del origen.

## 1. Empieza por diseñar límites de dominio, no por copiar endpoints

El punto de integración correcto parte de una pregunta: ¿qué conoce con certeza tu producto? Normalmente conoce quién compra, qué se factura, importes, impuestos comerciales, moneda, número y fecha cuando ya forman parte de su proceso. También dispone de un identificador interno que puede convertirse en eventId. Esos hechos deben salir del software origen porque otro sistema no puede reconstruirlos mejor. En cambio, tenant fiscal, instalación, certificado, entorno, permisos y ciertas clasificaciones no deberían llegar como decisiones libres desde un cliente que simplemente posee una API key.

Esta frontera evita dos motores fiscales. Si cada SaaS implementa sus propias reglas de XML, hash, transporte y respuestas, cualquier cambio exige coordinar releases entre producto y normativa. Al concentrar esa capa en el bridge, el equipo cliente mantiene un contrato de integración relativamente estable. La aplicación puede seguir evolucionando su modelo, UI y negocio; cuando una regla del core cambia, el adapter solo necesita seguir entregando hechos coherentes. El objetivo no es esconder la fiscalidad, sino asignar cada responsabilidad al componente que puede gobernarla y auditarla mejor.

## 2. El cliente de VeriFactu pertenece al backend, nunca al navegador

El SDK declara de forma explícita uso server-side only. La API key del conector no debe llegar a JavaScript del navegador, aplicaciones públicas ni contextos que no necesiten custodiar secretos. En una arquitectura habitual, el frontend envía la acción al backend de tu producto; allí se autentica al usuario, se comprueba el permiso funcional y se llama a Puente VeriFactu con la credencial correspondiente a la instalación. La respuesta se transforma después en un estado de producto que puede mostrarse sin revelar material sensible.

Este patrón simplifica rotación y segregación de permisos. Cada instalación puede tener credenciales diferentes y el servidor decide cuál utilizar a partir del contexto autenticado del negocio. También permite aislar workers y colas: un job que procesa facturas no necesita exponer su token a la UI. Si el producto es multi-tenant, no conviene derivar el tenant fiscal directamente de un organizationId enviado por frontend; ese valor debe resolverse por la credencial y las relaciones del servidor. Seguridad y multitenancy forman parte del contrato, no son una capa opcional añadida después.

## 3. Usa SDK por comodidad, pero diseña contra el contrato REST

El SDK expone preflight, preflightMapped, issue, issueMapped y getFiscalRecord. También normaliza errores en PuenteVerifactuError. Esto evita repetir código de autenticación, parseo y manejo básico en cada integración Node. Sin embargo, la arquitectura no debe depender de una magia exclusiva del SDK: REST API v1 es la fuente del contrato. Un equipo en otro lenguaje puede reproducir exactamente la misma semántica con HTTP y un adapter pequeño. Esa neutralidad es importante para ERP Java, servicios .NET, Python o backends que no quieran introducir una dependencia adicional.

Diseñar contra el contrato también ayuda con versionado. El adapter debe saber qué necesita garantizar —preflight sin efectos, issue idempotente, consulta por recordId, errores estructurados— en lugar de acoplarse a detalles internos de una implementación JavaScript. El SDK puede evolucionar manteniendo esa superficie. Para pruebas, se puede mockear el cliente o ejecutar Contract Suite contra un conector real de test. Esta separación entre protocolo y helper mantiene el ecosistema abierto a tecnologías diferentes sin sacrificar invariantes fiscales.

## 4. InvoiceIntent y MappingProfile resuelven dos escenarios de ownership distintos

Cuando tu equipo controla completamente el modelo de facturas, generar InvoiceIntent permite tratar la integración como otro contrato tipado. Puedes validar que importes se serializan con precisión decimal, que fechas siguen el formato esperado y que cada fuente tiene un sourceInvoiceId estable. Es una opción limpia para software nuevo o plataformas con un dominio bien definido. No significa que el cliente deba decidir todo: organización, instalación, sourceSystem, entorno y credenciales siguen resolviéndose en servidor aunque construyas el intent canónico.

MappingProfile encaja mejor cuando el producto ya tiene un payload estable que no conviene transformar en cada release o cuando varios clientes utilizan variantes del mismo software. El perfil server-side traduce rutas, puede aportar configuración fija y deja un punto de adaptación auditable fuera del código cliente. preflightMapped e issueMapped reutilizan la misma semántica que el modo canónico. Elegir uno u otro es una decisión de mantenimiento: el resultado final debe converger al mismo contrato e invariantes, no crear un comportamiento fiscal distinto por forma de entrada.

## 5. Preflight y errores estructurados deben formar parte del modelo de producto

Preflight permite saber si la intención es válida antes de crear una operación. Un SaaS puede utilizarlo al cerrar una factura, en una pantalla de revisión o dentro de un job previo a emisión. Si faltan datos, el resultado debe quedar en un estado funcional como bloqueado/requiere revisión en vez de presentarse como un error genérico de red. Ese enfoque convierte la validación fiscal en una parte observable del producto sin obligar al frontend a conocer reglas internas del bridge.

Los errores normalizados proporcionan code, status, retryable, correlationId y details sanitizados. El producto puede mapear códigos conocidos a instrucciones para usuario y enviar correlationId al soporte. retryable no significa reintentar infinitamente: un worker debe aplicar backoff y límites; un error no retryable debe salir de la cola automática. Tampoco conviene registrar todo el objeto indiscriminadamente. Los logs del cliente deberían conservar contexto operativo mínimo y evitar payloads completos, API keys o información que la capa fiscal ya protege.

## 6. Diseña eventId e idempotencia como parte de tu dominio, no como detalle HTTP

Connector Contract Suite v2 exige eventId antes de crear una operación nueva. Ese identificador debería representar una intención concreta y repetible: por ejemplo, la emisión de una factura con identidad interna estable, no el timestamp del intento HTTP. El adapter deriva una Idempotency-Key determinista para que dos entregas del mismo evento se reconozcan como la misma operación. Si el origen produce eventos distintos —factura original y rectificativa, por ejemplo— deben utilizar identidades diferentes aunque compartan pedido o cliente.

El diseño debe sobrevivir a reintentos y despliegues. Si un worker cae y vuelve a leer el mismo mensaje, eventId no cambia. Si una cola redelivera después de varias horas, tampoco. Generar un UUID nuevo dentro del handler destruiría precisamente la protección que se busca. Conviene almacenar eventId junto a la referencia local y, una vez se conoce, recordId. Así soporte puede reconstruir la cadena source operation → eventId → idempotency → recordId sin depender de logs temporales.

## 7. recordId cambia el problema: después de crear ya no estás intentando emitir, estás reconciliando

Una vez que issue devuelve recordId, ese identificador pasa a ser la referencia durable de la operación. status(recordId) consulta estado normalizado y sync con recordId debe limitarse a esa consulta. La Contract Suite comprueba explícitamente que no se ejecutan preflight ni issue en esa rama. Este detalle previene el bug más peligroso de una integración: interpretar una imposibilidad temporal de consultar como permiso para crear una segunda operación.

Incluso si status responde con un fallo retryable, la solución es reintentar reconciliación, no reiniciar el flujo de emisión. El producto puede marcar la factura como pending/review y continuar más tarde. Para UX, no es necesario mostrar recordId completo a todos los usuarios, pero sí conviene que soporte tenga acceso controlado a la referencia y correlationId. La reconciliación convierte un sistema distribuido en un flujo recuperable: el estado puede demorarse, pero la identidad no se pierde.

## 8. Convierte los invariantes del adapter en un gate CI con Connector Contract Suite v2

La suite no depende del framework del origen. El módulo bajo prueba exporta una muestra y una función createConnectorUnderTest que recibe client, profileId y sourceName. El conector ofrece cuatro operaciones: preflight, send, status y sync. El runner comprueba preflight sin efectos, eventId obligatorio, claves estables, eventos distintos con identidades distintas, consulta por recordId, reconciliación sin reissue, retry de issue con la misma clave y payload fuente no mutado. También comprueba que el adapter no inyecta tenant, instalación, certificados, passphrases, entorno o permisos.

El comando devuelve JSON estable con suiteVersion 2 y exit code 1 al fallar, por lo que puede integrarse directamente en GitHub Actions u otro CI. Esto crea una definición objetiva de compatible con el contrato de Puente. Aun así, no todas las afirmaciones comerciales se derivan de este gate: pasar la suite no demuestra que una versión concreta de un ERP funcione, ni sustituye un smoke de esa plataforma, ni certifica cumplimiento regulatorio. Debe combinarse con tests propios de negocio y con el gate fiscal separado.

## 9. Webhook es una alternativa de entrada, no una semántica fiscal diferente

Los productos event-driven pueden utilizar POST /v1/webhooks/{profileId}. El evento se firma mediante HMAC-SHA256 y timestamp anti-replay y conserva una identidad idempotente. El secreto está asociado a la instalación y profileId determina el mapping autorizado. El payload no puede concederse otro tenant. Esta ruta permite integrar plataformas que ya tienen un sistema de webhooks configurable sin construir un cliente REST completo dentro del producto.

Pero el pipeline posterior es el mismo: mapping, preflight, idempotencia, creación y estado. Por eso las mismas reglas de identidad se mantienen. Si el proveedor repite un webhook, el evento debe tener el mismo identificador. Si la aplicación cambia el contenido manteniendo identidad, debe detectarse como conflicto en vez de sobrescribir silenciosamente una operación. Y si después existe recordId, el sistema vuelve al modelo de reconciliación. Elegir webhook cambia la forma de entrada, no la disciplina del contrato.

## 10. Diseña observabilidad y soporte sin copiar secretos ni XML a tus logs

Una integración distribuida necesita trazabilidad. El producto debería poder relacionar su invoiceId con eventId, recordId, estado normalizado, último error y correlationId. Ese conjunto permite saber qué operación se estaba procesando y pedir soporte con una referencia común. No es necesario replicar XML AEAT, certificados ni mensajes completos en logs del SaaS. De hecho, hacerlo amplía exposición de datos y crea dos lugares donde aplicar políticas de seguridad y retención.

La interfaz puede presentar estados simplificados —pendiente, aceptado, requiere revisión— manteniendo detalles técnicos en una vista de soporte. Para jobs automáticos, métricas de retries y edad del estado ayudan a detectar colas atascadas. Un recordId que permanece pendiente durante demasiado tiempo debe disparar reconciliación/alerta, no otro issue. La observabilidad correcta refuerza las mismas fronteras que la idempotencia: distinguir identidad, estado y transporte evita tomar decisiones destructivas por falta de información.

## 11. Define un release gate técnico antes del gate regulatorio de producción

Un adapter debería llegar a producción de producto después de pasar tests de dominio, Contract Suite, preflight realista, escenarios de retry y recuperación. Si integra una plataforma concreta, añade un smoke de esa versión o capability antes de declararla soportada. También conviene probar rotación de credenciales y comportamiento cuando Kairoseth Fiscal no está disponible temporalmente. Un circuito breaker o cola puede proteger la UX, pero nunca debe convertir indisponibilidad en creación repetida de operaciones con identidades nuevas.

Después existe un gate diferente: el fiscal. Antes de AEAT producción se revisan fuentes regulatorias vigentes, identidad del obligado, certificado, configuración, evidencias y autorización explícita. El producto puede estar técnicamente listo mientras producción fiscal permanece cerrada. Mantener ambos gates evita que una release de software se convierta accidentalmente en una decisión regulatoria. Connector Contract Suite aporta evidencia de integración; el gate de producción aporta la decisión fiscal y operativa correspondiente.

## Conclusiones

- Integra desde backend: API key, certificado, tenant y entorno nunca pertenecen al navegador.
- Elige InvoiceIntent o MappingProfile según ownership del modelo, manteniendo la misma semántica de preflight e issue.
- eventId e Idempotency-Key deben representar una identidad durable; no regeneres claves en cada retry.
- Cuando existe recordId, sync solo reconcilia; un fallo de status nunca autoriza un nuevo issue.
- Ejecuta Connector Contract Suite v2 en CI y comunica su alcance correctamente: contrato de integración, no certificación regulatoria.

## Sources

- [Puente VeriFactu SDK](https://github.com/Emmakex/puente-verifactu/blob/main/packages/sdk/README.md) — Kairoseth / Puente VeriFactu
- [Connector Contract Suite v2](https://github.com/Emmakex/puente-verifactu/blob/main/packages/connector-contract-suite/README.md) — Kairoseth / Puente VeriFactu
- [Contrato API v1](https://github.com/Emmakex/puente-verifactu/blob/main/docs/api-contract.md) — Kairoseth / Puente VeriFactu
- [AEAT — Sistemas Informáticos de Facturación y VERI*FACTU](https://sede.agenciatributaria.gob.es/Sede/iva/sistemas-informaticos-facturacion-verifactu.html) — Agencia Estatal de Administración Tributaria

## External resources

- [Portal oficial AEAT SIF / VERI*FACTU](https://sede.agenciatributaria.gob.es/Sede/iva/sistemas-informaticos-facturacion-verifactu.html): Información técnica, FAQ y referencias normativas oficiales.

## Producto relacionado

- [Software VeriFactu](https://kairoseth.com/products/kairoseth-fiscal): Software VeriFactu adaptable para conectar WooCommerce, PrestaShop, ERP, CRM, Excel, software propio y sistemas locales sin sustituir el sistema de origen.
- [Solicitud personalizada](https://kairoseth.com/custom-requests)
