ago 20264 min de lectura

Cómo sacamos un número confiable de un banco sin API

En México, una cuenta de banco no viene con API. Los datos llegan en un PDF, una vez al mes.

Construimos y operamos un club de miembros que se llama Compound, en compounding.club. Le dice a cada miembro dónde está su dinero en realidad. Aquí no hay sincronización bancaria a la cual conectarse, y entregarle a un agregador tus credenciales del banco es un intercambio que no quisimos hacer. Así que el insumo es el estado de cuenta mismo.

Convertir un PDF en números es exactamente el tipo de trabajo que un modelo hace bien. Confiar en esos números es otro problema, y es el que vale la pena contar.

Dónde va el modelo

El modelo transcribe. Lee el documento y anota lo que viene impreso: la fecha, la descripción tal como aparece, el monto, y si el renglón es un cargo, una comisión, intereses, un pago a la tarjeta o una devolución. El formato cambia entre bancos y se mueve entre meses. Esa ambigüedad es el trabajo.

Ahí se detiene. No decide qué significa nada de eso.

Dónde no va

Las categorías salen de código normal. Una lista fija de reglas por comercio mapea una descripción a una categoría; gana la primera coincidencia. El modelo puede proponer una categoría, y su propuesta se usa solo para comercios que las reglas nunca han visto. Una regla siempre le gana. Las compras a meses se leen de las marcas que imprime el banco, nunca de una suposición.

La razón es aburrida e importa. Las reglas se pueden inspeccionar. Cuando una categoría sale mal, puedes encontrar la línea que la hizo salir mal y cambiarla. Un modelo que recategoriza un año de gastos sin avisar no te deja nada que arreglar.

El candado

Luego viene la aritmética, que es de donde sale la confianza de verdad. Un estado de cuenta de tarjeta imprime su propio resumen: saldo anterior, total de cargos, total de pagos, saldo nuevo. Los renglones transcritos tienen que reproducir esas cifras, con margen de un centavo. Si no cuadran, no se importa nada de ese archivo. Ni los renglones que se ven bien. Nada.

Un renglón inventado rompe el total de cargos. Un renglón perdido lo rompe para el otro lado. El banco ya hizo esta aritmética y ya imprimió la respuesta, así que usamos su respuesta como la prueba.

Los imports parciales son la trampa. Quedarte con lo que sí se pudo leer se siente útil, y produce una contabilidad que está casi bien, sin nada que marque qué parte no lo está. El rechazo molesta un minuto. Un saldo mal sin avisar te cuesta el producto.

El resto de la disciplina

De la misma idea salen dos hábitos. El archivo original nunca se guarda: los bytes se leen en memoria y se descartan, y solo sobreviven la fecha, el comercio, el monto y la categoría. Las secuencias largas de dígitos se limpian de cada string antes de que exista un renglón, así que un número de tarjeta o de cuenta no puede llegar al almacenamiento aunque el estado de cuenta lo traiga impreso.

Las pruebas también son simples. Nueve archivos de autoverificación, puros asserts, sin framework de pruebas. Uno de ellos toma un estado de cuenta que cuadra, le mete un cargo que nunca existió, y verifica que el import lo rechace.

Esto aplica a cualquier funcionalidad de IA que viva cerca de un número que importa. Dale al modelo la parte genuinamente ambigua, que es leer algo revuelto. Mantén deterministas las partes deterministas, sobre todo la decisión de escribir algo o no escribir nada. Un import que se niega es mejor que un import que queda mal sin avisar. En una ruta de dinero, negarse es el feature.

¿Estás construyendo algo así?

Habla con un fundador

Un fundador responde en un día hábil.