# Arquitectura de la facturación centralizada

Cómo encajan UTILIA OS, tu aplicación y la pasarela de pago al facturar y cobrar: identificadores, puente de identidad, cobro recurrente y avisos.

UTILIA OS actúa como **centro fiscal** y **centro de cobro** de las aplicaciones que conectas: numera y emite las facturas, guarda el estado de cada cobro y avisa a tu aplicación de todo lo que pasa. Con la clave de API de tu aplicación, y la facturación activada para ella, puedes emitir facturas con la numeración de la organización, guardar tarjetas, montar cuotas y cobrarlas. Esta página explica cómo encajan las piezas para que diseñes esa integración sabiendo qué hace cada una. El recorrido práctico, paso a paso, está en la [guía de facturación y cobro](https://os.utilia.ai/docs/developers/api/billing-guide).

## Visión general

Tres actores trabajan juntos:

- **UTILIA OS**: numera las facturas de forma correlativa, genera su PDF, mantiene el estado fiscal, guarda el metadato de cada cobro y expone la API externa.
- **Stripe**: gestiona los datos de tarjeta (PCI DSS), ejecuta los cobros, enruta el dinero a la cuenta bancaria de la organización y notifica por webhooks.
- **Tu aplicación externa**: da de alta a sus usuarios, emite facturas, monta suscripciones, recoge la autorización de cobro, lanza cobros y recibe los avisos de todo lo anterior.

## Pagos con tarjeta: una cuenta de Stripe por organización

Cada organización de UTILIA OS conecta **su propia cuenta de Stripe**, de tipo estándar. UTILIA OS actúa como plataforma, pero los cobros se enrutan a la cuenta de la organización con la cabecera `Stripe-Account` en cada llamada.

Ventajas de este modelo:

- El dinero llega directamente al banco de la organización, no al de UTILIA OS, y sin comisión de UTILIA OS por transacción.
- Cada organización mantiene independencia total sobre su cuenta de Stripe: panel propio, devoluciones y disputas.
- Los datos sensibles de las tarjetas viven solo en Stripe: ni UTILIA OS ni tu aplicación los ven.

Al navegador solo llega la **clave publicable de la plataforma**, que es pública por diseño, acompañada del identificador de la cuenta conectada (`stripeAccount`). No existe una clave publicable propia de cada cuenta conectada: con cargos directos, Stripe exige exactamente esa combinación.

### Saber si la organización puede cobrar

Antes de intentar un cobro, tu aplicación puede preguntar si la organización está lista para cobrar con tarjeta con [`GET /external/v1/payment-methods/readiness`](https://os.utilia.ai/docs/developers/api/payment-methods#saber-si-la-organización-puede-cobrar). Devuelve `platformAvailable`, `organizationCanCharge`, `livemode` y un motivo estable (`PLATFORM_DISABLED`, `NO_ACCOUNT`, `ONBOARDING_INCOMPLETE`, `CHARGES_DISABLED`, `ACCOUNT_DEAUTHORIZED` o `READY`). Es el mismo criterio que usan las pantallas del panel.

## Identificadores que verás

En las respuestas y en los avisos aparecen identificadores de Stripe (`acct_…` de la cuenta conectada, `cus_…` del cliente, `pm_…` de la tarjeta y `pi_…` de cada intento de cobro) junto a los de UTILIA OS. Una factura emitida por tu aplicación lleva `source: EXTERNAL_APP` y la referencia a tu aplicación y a su usuario externo.

## Los usuarios de tu aplicación no se mezclan con el CRM

El CRM no ve a los usuarios externos de ninguna aplicación como tales, solo sus propios clientes. Cuando un usuario externo necesita facturarse, el puente de identidad crea su ficha de cliente (se explica más abajo).

## Flujo: cobro desde el portal del cliente

Cuando el cliente paga una factura desde el portal del cliente:

1. Pulsa **Pagar ahora** y el portal llama a `POST /portal-invoices/:id/pay`.
2. UTILIA OS comprueba sus permisos y el estado de la factura, crea el cobro en Stripe con el cliente delante y devuelve el `clientSecret`.
3. El portal confirma el pago con Stripe Elements.
4. Stripe avisa a UTILIA OS con `payment_intent.succeeded`. UTILIA OS comprueba la firma, registra el aviso para no procesarlo dos veces y marca la factura como cobrada.
5. El cliente recibe el correo, el portal se actualiza al momento y, si la factura es de una aplicación externa, esta recibe el aviso `INVOICE_PAID`.

## Flujo: cobro automático de una factura recurrente nativa

Este flujo es el de las suscripciones creadas desde el panel para un cliente del CRM. Una aplicación externa usa el mismo motor por su propia vía, que se describe más abajo.

1. Cada día a las 08:00 UTC, el proceso de facturas recurrentes emite las que vencen ese día, con su número.
2. Si la suscripción tiene el cobro automático con tarjeta (`chargeMode = AUTO_STRIPE`), el cliente firmó una autorización de cobro vigente y la organización tiene activado el cobro automático, UTILIA OS programa el cobro de esa factura. Si falta cualquiera de las tres cosas, la factura queda emitida y no se cobra sola. Marcar una tarjeta como predeterminada no autoriza ningún cobro.
3. El día programado, UTILIA OS vuelve a comprobar la factura, la suscripción, la autorización y su tarjeta, y cobra sin el cliente delante SIEMPRE la tarjeta de la autorización, con clave de idempotencia. Si Stripe confirma el cobro, la factura pasa a cobrada. Si el banco pide verificar al cliente, este recibe un correo para completarlo en el portal. Un adeudo que Stripe deja en curso no se repite: se espera a que se liquide.
4. Si el cobro falla, se reintenta a los 3, 7 y 14 días (valores por defecto), con las mismas comprobaciones en cada intento. Agotados los reintentos, el cobro programado queda en fallo definitivo, se avisa al equipo y sale el evento `INVOICE_PAYMENT_FAILED`. Si la factura se paga por otro canal, se anula o se rectifica, o el cliente retira su autorización, los reintentos pendientes se cancelan.

## Flujo: factura creada por aplicación externa, pagada desde la propia app

**Factura de tu aplicación, pagada en tu aplicación**

Participantes: Tu aplicación, UTILIA OS y Stripe.

1. Tu aplicación → UTILIA OS: `POST /external/v1/invoices`. Con el usuario y las líneas de la factura.
2. UTILIA OS (por su cuenta): Comprueba que la facturación de la aplicación está activa y su tope, numera y emite la factura.
3. UTILIA OS → Tu aplicación (respuesta): La factura emitida. Con origen EXTERNAL_APP.
4. Tu aplicación → UTILIA OS: `POST /external/v1/invoices/:id/pay`. Cuando tu usuario pulsa Pagar.
5. UTILIA OS → Tu aplicación (respuesta): clientSecret, publishableKey y stripeAccountId
6. Tu aplicación → Stripe: Confirma el pago con Stripe Elements. Con la clave publicable de la plataforma y stripeAccount.
7. Stripe → UTILIA OS (respuesta): payment_intent.succeeded. La factura pasa a cobrada.
8. UTILIA OS → Tu aplicación: Aviso INVOICE_PAID. Actualizas tu base de datos y avisas a tu usuario.

_El SDK de JavaScript envuelve las dos llamadas: sdk.invoices.create y sdk.payments.payInvoice._

UTILIA OS recibe de Stripe la confirmación de cada cobro, verifica su firma y la procesa una sola vez aunque Stripe la reintente.

## Flujo: cuota recurrente de una aplicación externa

Es el caso de una aplicación que cobra cada mes a sus usuarios. La pieza que lo hace posible es el **puente de identidad**: el usuario de la aplicación se materializa como ficha de cliente del CRM, y a partir de ahí reutiliza el motor financiero entero.

**Cuota recurrente de una aplicación externa**

Participantes: Tu aplicación, UTILIA OS y Stripe.

1. Tu aplicación → UTILIA OS: `POST /external/v1/users/identify`. Da de alta al usuario o actualiza sus datos fiscales.
2. UTILIA OS (por su cuenta): Puente de identidad: la primera vez que se factura, se guarda tarjeta o se crea suscripción, crea su ficha de cliente del CRM.
3. Tu aplicación → UTILIA OS: `POST /external/v1/payment-methods/setup-intent`. Prepara el guardado de la tarjeta del usuario.
4. Tu aplicación → UTILIA OS: `POST /external/v1/payment-authorizations`. Tras enseñar el texto de consent-text: versión, momento, IP y navegador.
5. Tu aplicación → UTILIA OS: `POST /external/v1/subscriptions`. chargeMode AUTO_STRIPE con la autorización recién firmada.
6. UTILIA OS (por su cuenta): Cada periodo emite la factura de tu aplicación y, si el correo está activo, la envía con su PDF.
7. UTILIA OS → Tu aplicación: SUBSCRIPTION_INVOICE_GENERATED. Aviso con la factura y emailSent.
8. UTILIA OS → Stripe: Cobro sin el usuario delante. Contra la autorización firmada.
9. Stripe → UTILIA OS (respuesta): payment_intent.succeeded. La factura pasa a cobrada.
10. UTILIA OS → Tu aplicación: CHARGE_SUCCEEDED. Renuevas el servicio.

_Los avisos de suscripciones y cobros son siempre dirigidos: solo los recibe tu aplicación._

Lo que puede torcerse por el camino:

- **Sin autorización vigente**, `POST /subscriptions` en cobro automático responde `409 PAYMENT_AUTHORIZATION_REQUIRED`. Si la organización tiene apagado el cobro automático, `409 AUTO_CHARGE_DISABLED_FOR_ORGANIZATION`, sin `nextStep`. Nunca se pasa a cobro manual en silencio.
- **Si el cobro falla**, llegan `CHARGE_FAILED` y `CHARGE_RETRY_SCHEDULED` en cada reintento, hasta `CHARGE_RETRIES_EXHAUSTED`. Antes de cada intento llega `CHARGE_STARTED`.
- **Si el banco pide verificar al usuario**, llega `CHARGE_REQUIRES_ACTION`: pides el enlace público de la factura y llevas allí a tu usuario.
- **Con `clientId` en `identify`**, el puente reutiliza una ficha que creó tu propia aplicación. Una ficha dada de alta por el equipo desde el panel no se toca (se explica más abajo).

Consecuencias de que el usuario externo sea un cliente del CRM: sus facturas aparecen en Finanzas con el origen visible y el filtro por aplicación y cuentan como cualquier otra, y su ficha en el CRM muestra de qué aplicación viene.

### El puente no cruza hacia las fichas nativas

Cada ficha de cliente guarda qué aplicación externa la creó. El puente solo reutiliza, converge o enlaza fichas con esa marca, o que ya tengan un usuario de la misma aplicación. Una ficha dada de alta por el equipo desde el panel queda fuera del alcance de la API externa, aunque coincidan el identificador fiscal o el correo: en ese caso se crea una ficha nueva y la coincidencia se registra en el histórico de auditoría para que el equipo decida.

Unir las dos fichas sigue siendo posible desde el panel, con sesión iniciada, permiso y alcance sobre la ficha. En ese camino la aplicación gana la facturación de esa persona, pero **no** hereda sus tarjetas guardadas ni las autorizaciones de cobro que firmó en el portal del cliente: el cliente de la pasarela no converge sobre una ficha nativa.

## Avisos salientes hacia las aplicaciones externas

Para cada cambio relevante, UTILIA OS entrega un aviso firmado a las aplicaciones suscritas. Los del ciclo de facturación y cobro son:

| Dominio | Eventos |
| - | - |
| Facturación | `INVOICE_CREATED`, `INVOICE_SENT`, `INVOICE_PAID`, `INVOICE_PARTIALLY_PAID`, `INVOICE_PAYMENT_FAILED`, `INVOICE_OVERDUE`, `INVOICE_CANCELLED`, `INVOICE_REFUNDED`, `INVOICE_REFUND_CANCELLED`, `INVOICE_RECTIFIED`, `INVOICE_RECTIFICATION_CREATED`, `INVOICE_RECTIFICATION_METADATA_UPDATED` |
| Métodos de pago | `PAYMENT_METHOD_ADDED`, `PAYMENT_METHOD_REMOVED`, `PAYMENT_METHOD_EXPIRING` |
| Autorizaciones de cobro | `PAYMENT_AUTHORIZATION_GRANTED`, `PAYMENT_AUTHORIZATION_REVOKED`, `PAYMENT_AUTHORIZATION_CONSUMED` |
| Suscripciones | `SUBSCRIPTION_CREATED`, `SUBSCRIPTION_UPDATED`, `SUBSCRIPTION_PAUSED`, `SUBSCRIPTION_RESUMED`, `SUBSCRIPTION_CANCELLED`, `SUBSCRIPTION_COMPLETED`, `SUBSCRIPTION_INVOICE_GENERATED`, `SUBSCRIPTION_PAYMENT_AUTHORIZATION_PENDING` |
| Cobros programados | `CHARGE_SCHEDULED`, `CHARGE_STARTED`, `CHARGE_SUCCEEDED`, `CHARGE_FAILED`, `CHARGE_REQUIRES_ACTION`, `CHARGE_RETRY_SCHEDULED`, `CHARGE_RETRIES_EXHAUSTED`, `CHARGE_CANCELLED` |

Regla de enrutado:

- Los dieciséis de **suscripciones y cobros** son siempre **dirigidos**: sin aplicación dueña no hay destinatario.
- Los de **facturas, métodos de pago y autorizaciones** son dirigidos cuando el recurso pertenece a un usuario de una aplicación externa, y por **difusión** cuando es propio de la organización.

El catálogo completo, con el contenido de cada aviso campo a campo, está en [Avisos: contenido y catálogo de eventos](https://os.utilia.ai/docs/developers/webhooks/events).

## Permisos del equipo implicados

Estos son permisos de **personas del equipo**, no de aplicaciones externas. Se asignan a los roles desde los ajustes de la organización, y no deben confundirse con los permisos de la API externa, que se conceden por aplicación desde el panel de aplicaciones externas.

- Configuración y consulta de la pasarela, y devoluciones desde el panel.
- Consulta y gestión de las tarjetas guardadas de un cliente.
- Cobro de una factura desde el panel.
- Consulta y gestión de las suscripciones del CRM.
- Consulta y cancelación de los cobros programados.
- Pago y gestión de tarjetas desde el portal del cliente.

El catálogo de permisos de la **API externa**, que es otra cosa, está en [Gestión de scopes de aplicaciones externas](https://os.utilia.ai/docs/developers/api/scopes).

## Siguiente paso

Pon en práctica el recorrido completo, del alta del usuario a la renovación sin nadie delante, con la [guía de facturación y cobro](https://os.utilia.ai/docs/developers/api/billing-guide).
