Automatizar la descarga de extractos bancarios: de herramienta interna a SaaS
Creamos un script para descargar automáticamente nuestros extractos bancarios de Wise. Es una tarea de una tarde. La pregunta más interesante —cuya respuesta requirió bastante más tiempo— era si la misma herramienta podía servir a otras empresas con el mismo problema y qué haría falta para dar ese paso de forma responsable. El recorrido desde un script de línea de comandos ejecutado en la computadora portátil de un desarrollador hasta un servicio en contenedores con notificaciones por correo electrónico puso de manifiesto decisiones que conviene documentar, especialmente para equipos que evalúan si merece la pena convertir una automatización interna en un producto.
El problema original
Wise ofrece una API para acceder a los datos de las cuentas, pero el procedimiento habitual de la mayoría de los equipos financieros consiste en iniciar sesión en la interfaz web y descargar manualmente un extracto en CSV al final de cada mes. Para una sola cuenta con una sola divisa, esto lleva dos minutos. Para operaciones con varias divisas en varias cuentas de Wise —algo habitual en empresas con flujos de pagos regionales— se convierte en una carga recurrente: alguien debe recordarlo, hacerlo de forma consistente y archivar los documentos correctamente.
La API de Wise expone los endpoints necesarios. Permite obtener una lista de perfiles, consultar los saldos por divisa y solicitar exportaciones de extractos en CSV o PDF para cualquier intervalo de fechas. La autenticación utiliza un token de acceso personal que se genera en el panel de desarrolladores de Wise. Si su alcance se configura correctamente, el token solo permite leer datos de las cuentas, por lo que puede almacenarse y utilizarse sin el perfil de riesgo de un token capaz de iniciar transferencias.
Nuestra primera implementación tenía unas 80 líneas de Python. Leía las credenciales de variables de entorno, recorría los perfiles y los saldos por divisa, construía las solicitudes de extractos del mes anterior y guardaba los archivos resultantes en un directorio local. Se ejecutaba manualmente. En aquel momento bastaba para nuestras necesidades.
De script a servicio programado
Pasar de «se ejecuta manualmente» a «se ejecuta automáticamente» introduce otro tipo de problemas. Si un script falla en silencio durante una ejecución manual, se detecta de inmediato. Si lo hace cuando se ejecuta de forma programada el primer día de cada mes, puede pasar inadvertido durante varios meses y dejar un vacío en el archivo de extractos que se descubre durante una auditoría.
Trasladamos el script a un contenedor Docker con un punto de entrada sencillo y añadimos una capa que envía una notificación por correo electrónico al terminar, tanto si la ejecución tiene éxito como si falla. El correo resume las cuentas y divisas procesadas, cuántos archivos se descargaron y sus tamaños. En caso de fallo, incluye la salida de error. Es una inversión mínima en observabilidad, pero cambia las condiciones de operación: la automatización pasa a estar supervisada aunque se ejecute sin intervención.
La programación se gestiona con GitHub Actions, no con cron dentro del contenedor. Utilizamos un activador schedule en un flujo de trabajo que se ejecuta al inicio de cada mes; una programación cron por sí sola no permite seleccionar los días hábiles, por lo que omitir los fines de semana y los días festivos requiere una comprobación adicional de la fecha en el flujo de trabajo. El flujo obtiene el repositorio, construye la imagen Docker si ha cambiado, ejecuta el contenedor con secretos inyectados desde GitHub Secrets y carga los archivos de salida como artefactos del flujo de trabajo. Estos se conservan durante 90 días y ofrecen un archivo recuperable independiente del almacenamiento local.
GitHub Actions tiene una ventaja práctica frente a una tarea cron en un servidor: la visibilidad. El historial del flujo muestra cada ejecución, su duración, su código de salida y los artefactos que produjo. Una tarea cron genera registros que pueden pasar inadvertidos y depende de que el servidor esté disponible. Para una tarea mensual, disponer de un historial auditable y de una definición del flujo bajo control de versiones compensa la pequeña carga de configuración.
Qué exige realmente una arquitectura multiinquilino
Después de varios meses de funcionamiento fiable de la versión en contenedores, colegas de otras empresas preguntaron si podían utilizarla. La pregunta parece sencilla: ¿pueden otras personas ejecutar su herramienta? Sin embargo, esto abarca modelos operativos muy distintos, con implicaciones también muy distintas.
El modelo más sencillo consiste en compartir el repositorio y la documentación para que otros ejecuten la herramienta en su propio entorno de GitHub Actions o Docker, sin ofrecer soporte. Es una distribución de código abierto, no un producto SaaS. Toda la carga operativa recae en el usuario.
El siguiente paso es alojar la herramienta y permitir que los usuarios proporcionen sus propios tokens de la API de Wise mediante una interfaz de configuración. Ahora se custodian credenciales. Esto genera de inmediato obligaciones de seguridad y cumplimiento normativo cualitativamente distintas de las de una automatización personal. Hay que responder a estas preguntas: ¿cómo se almacenan las credenciales?, ¿quién tiene acceso?, ¿qué ocurre si el almacenamiento se ve comprometido? y ¿qué responsabilidad se asume si alguien accede a la cuenta de Wise de un usuario a través de la plataforma?
El paso posterior implica facturación, soporte, compromisos de nivel de servicio y la carga operativa de mantener infraestructura para varios usuarios. Nada de esto es insuperable, pero cada punto exige decidir cuánto se está dispuesto a invertir en ingeniería y qué costo operativo recurrente se puede asumir.
La evaluación como SaaS
Evaluamos la opción enumerando los requisitos de una versión multiinquilino mínima y calculando con realismo el costo de cada uno. Solo gestionar las credenciales —almacenar los tokens de la API de Wise de forma segura, ofrecer una interfaz para administrarlos e implementar controles que impidan el acceso entre inquilinos— supone una semana de ingeniería antes de abordar la descarga de extractos. Si se añaden autenticación de usuarios, facturación, un servicio de correo con gestión de bajas y monitoreo de fallos de tareas por inquilino, el resultado es un producto que exige una inversión sostenida para mantenerlo de forma segura.
El mercado de esta herramienta concreta también es limitado. Las empresas con suficiente tamaño para querer automatizar la descarga de extractos suelen disponer de software contable que se integra directamente con Wise o de equipos financieros que ya resolvieron el problema por su cuenta. El mercado potencial está en el segmento intermedio: empresas con suficiente tamaño para sentir el problema, pero que aún no utilizan sistemas contables integrados.
Concluimos que, en la etapa actual, la herramienta no era una buena candidata a SaaS para nuestro equipo. Los ingresos potenciales no justificaban la inversión en ingeniería y operaciones. La distribución de código abierto satisface la necesidad real sin crear obligaciones que no podemos sostener.
Qué mantuvimos y qué cambiamos
La herramienta interna sigue funcionando. Con el tiempo añadimos salida en PDF además de CSV, envío de los extractos directamente a una dirección de correo en lugar de depender de la recuperación de artefactos del flujo, e intervalos de fechas configurables para solicitar extractos puntuales manualmente sin alterar la ejecución mensual programada.
El flujo de GitHub Actions se convirtió en el mecanismo de despliegue de referencia. Lo documentamos en el README del repositorio con suficiente detalle para que alguien que no haya utilizado la herramienta en seis meses entienda qué hace y cómo operarla. Conviene aplicar esta disciplina a cualquier automatización interna: trate sus herramientas internas como si tuviera que entregárselas a otra persona, porque tarde o temprano tendrá que hacerlo.
La lección más duradera de este proyecto es la distancia entre «esto funciona para nosotros» y «esto funciona para otros». Las herramientas internas se adaptan a restricciones concretas: las prácticas de gestión de credenciales, las convenciones de almacenamiento de archivos y la infraestructura de correo. Hacerlas suficientemente generales para que otros las utilicen no consiste solo en añadir un archivo de configuración. Exige eliminar supuestos que solo se reconocen como tales cuando otra persona intenta utilizar la herramienta y tropieza con ellos.