Un solo ingeniero. Una plataforma a medida completa. 12 cuentas de marketplace. ~100 pedidos al día. 5 empleados usándola a diario. Esta es la historia técnica completa de cómo diseñé, construí y operé toda la plataforma de producción que hay detrás de REUSALIA — desde el primer bot de Selenium hasta un ERP completo con APIs aplicando ingeniería inversa, pipelines de IA e integración con hardware físico.
El problema: gestionar un negocio real con procesos manuales
En abril de 2023 fundé REUSALIA — una empresa de e-commerce que compra palés de liquidación de Amazon, procesa el inventario y revende los artículos de forma individual en varios marketplaces (Wallapop, eBay, PortalHero). El modelo de negocio es sencillo. Las operaciones que hay detrás, no.
Cada palé que llega contiene entre 50 y 200 artículos variados. Cada artículo hay que inspeccionarlo, fotografiarlo, categorizarlo, fijarle un precio, publicarlo en varias plataformas, hacer seguimiento de las ventas, empaquetarlo y enviarlo. Multiplica eso por miles de SKUs repartidos en 12 cuentas de marketplace y empiezas a entender la magnitud del problema.
Cuando empecé, todo era manual. Publicar un solo artículo en Wallapop llevaba entre 5 y 10 minutos de escritura. Los pedidos llegaban a través de varias cuentas y había que revisarlos uno a uno. El inventario se controlaba en Google Sheets. No había sistema — solo una persona con un portátil y un almacén.
Tres años después, toda la operación funciona sobre una plataforma que construí desde cero: un backend en FastAPI con más de 25 modelos de base de datos, un ERP a medida en Retool con más de 10 módulos operativos, APIs de marketplaces a las que apliqué ingeniería inversa, enriquecimiento de productos con IA y un puente de hardware personalizado que conecta interfaces en la nube con impresoras de etiquetas físicas. Esta es la historia de cómo evolucionó.
Fase 1: la era de Selenium (2023)
El primer problema técnico que resolví fue el más doloroso: publicar anuncios en Wallapop.
Wallapop no tiene API de publicación masiva. Ni importación por CSV. Ni forma alguna de publicar productos a escala. Cada anuncio había que crearlo manualmente a través de su interfaz web — rellenar el título, la descripción, la categoría, el precio, subir fotos, fijar la ubicación, confirmar. A 5-10 minutos por artículo, publicar un catálogo de 500-600 artículos era un trabajo a jornada completa.
Así que construí un bot de Selenium que automatizaba todo el flujo. Abría un navegador, navegaba hasta el formulario de publicación, rellenaba cada campo, subía imágenes y enviaba. Cada anuncio tardaba en torno a 1 minuto (ralentizado de forma intencionada para evitar la detección).
Pero 1 minuto por artículo entre 600 artículos siguen siendo 10 horas. Y necesitaba volver a publicar cada 3 días para mantener el posicionamiento en el marketplace. Así que escalé de la única forma que podía: horizontalmente, repartiendo entre máquinas físicas.
Monté 5-6 PCs, me conecté a cada uno de forma remota mediante AnyDesk y lancé varias instancias del bot por máquina. Cada instancia usaba cookies y user agents distintos. De esta forma podía publicar todo mi catálogo en aproximadamente una hora. Cada 3 días dedicaba una hora a gestionar la flota distribuida de bots.
Era feo. Era frágil. Funcionaba.
Lo que aprendí
- La automatización no empieza por la elegancia — empieza por reducir el dolor
- A veces «escalar» significa 6 portátiles sobre una mesa, no Kubernetes
- La anti-detección importa desde el primer día: rotación de user agents, aleatorización de tiempos, aislamiento de sesiones
Fase 2: ingeniería inversa de la API privada de Wallapop (2023-2024)
A medida que el negocio crecía, también lo hacía la complejidad operativa. Pasamos de 10 pedidos al día a casi 100. De 1 cuenta de Wallapop a 12. El enfoque con Selenium ya no escalaba — ni para publicar, y desde luego no para la gestión de pedidos.
El problema era que Wallapop es un ecosistema cerrado. Sin API pública. Sin documentación. Sin integraciones de terceros. Todo ocurre dentro de su app y su web. Para la mayoría, eso es un muro. Para mí, era una invitación.
Empecé a interceptar el tráfico de red. Cada acción que realizaba en la web — explorar anuncios, consultar pedidos, leer chats — capturaba la petición HTTP, estudiaba las cabeceras, decodificaba los payloads y mapeaba la estructura de las respuestas.
El proceso de descubrimiento
Hacer ingeniería inversa de una API privada es trabajo de detective:
- Capturar — Usar las DevTools del navegador para interceptar cada petición durante una sesión
- Clasificar — Agrupar las peticiones por patrón de endpoint y método HTTP
- Decodificar — Analizar las cabeceras de la petición (sobre todo la de autorización), los parámetros de consulta y la estructura JSON de las respuestas
- Contrastar — Comparar las respuestas de distintas cuentas para identificar qué es específico de cada usuario y qué es universal
- Replicar — Construir un cliente en Python capaz de autenticarse y realizar las mismas peticiones fuera del navegador
- Iterar — Cuando Wallapop cambia su API (y lo hace), actualizar el cliente
A lo largo de 5 versiones principales del código del extractor, mapeé su sistema de autenticación (basado en cookies con bearer tokens), sus endpoints de gestión de pedidos, su API de chat y su sistema de metadatos de anuncios. El resultado: más de 2.100 líneas de código Python en producción capaz de:
- Extractor de pedidos — Recopilar todos los pedidos de las 12 cuentas, normalizar los datos e introducirlos en nuestro ERP. Este único script sustituyó lo que habrían sido ~5 horas de trabajo manual diario
- Extractor de chats — Recopilar datos de las conversaciones para analizar métricas del embudo de ventas: tiempos de respuesta, tasas de conversión, patrones de comportamiento de los clientes
- Extractor de anuncios — Monitorizar qué artículos reciben más visitas, cuáles necesitan reajuste de precio y cuáles conviene promocionar
La arquitectura multicuenta fue la parte más difícil. Cada cuenta tiene su propio ciclo de vida de autenticación: las cookies caducan, los tokens hay que refrescarlos, las sesiones se invalidan. Construí un gestor de autenticación centralizado que almacena las credenciales en PostgreSQL, refresca automáticamente los tokens entre sesiones y proporciona contextos de autenticación limpios a cada extractor.
Nadie más ha construido esto. Existen herramientas como PortalHero para la publicación masiva, pero nada para la extracción. Nuestros extractores son únicos — y son lo que hace posible gestionar una operación de 12 cuentas con un equipo de 5 en lugar de un equipo de operaciones manuales mucho mayor.
Fase 3: la plataforma central — FastAPI + PostgreSQL (2024-2025)
Con los extractores aportando datos de forma fiable, necesitaba un sitio donde esos datos vivieran y algo que hacer con ellos. Google Sheets ya no daba más de sí (eso es otra historia completa).
Diseñé la plataforma central en torno a tres principios:
- Única fuente de verdad — Cada dato vive en PostgreSQL. Sin hojas de cálculo, sin archivos locales, sin «ya lo actualizo luego»
- API primero — Toda operación pasa por el backend de FastAPI. El frontend del ERP a medida construido sobre Retool, los extractores, los motores de sincronización — todos hablan con la misma API
- Automatización operativa — Si un humano hace algo más de dos veces, debería estar automatizado
Diseño de la base de datos
El esquema de PostgreSQL tiene más de 25 modelos con más de 35 migraciones, que cubren:
- Inventario — Artículos, SKUs, categorías, estados, ubicaciones, fotos
- Pedidos — Seguimiento de pedidos multi-marketplace con flujos de estado
- Ventas y facturación — Seguimiento de ingresos, análisis de costes, cálculo de márgenes por artículo y por palé
- Autenticación — Almacenamiento centralizado de credenciales para todas las cuentas de marketplace
- Programación — Colas de tareas para operaciones automatizadas (ciclos de sincronización, ejecuciones de extracción)
- Incidencias — Reclamaciones de clientes, devoluciones, problemas de envío
Uso SQLModel (SQLAlchemy + Pydantic) para la capa ORM, lo que me da modelos con tipado seguro que sirven tanto para las operaciones de base de datos como para la serialización de la API. Alembic gestiona las migraciones y nunca he tenido que revertir ninguna en producción.
Arquitectura de la API
El backend de FastAPI expone unos 60 endpoints que cubren operaciones CRUD, lógica de negocio e integraciones. Decisiones de diseño clave:
- Inyección de dependencias para las sesiones de base de datos, la autenticación y la limitación de tasa
- Tareas en segundo plano para operaciones pesadas (importaciones masivas, ciclos de sincronización)
- Gestión estructurada de errores con códigos de error específicos del negocio
- Modelos de petición/respuesta validados en la frontera de la API — si entran datos incorrectos, falla de forma ruidosa y temprana
Fase 4: el ERP — frontend en Retool (2025)
Una base de datos y una API no sirven de nada si tu equipo no puede interactuar con ellas. Necesitaba una interfaz que 6 empleados no técnicos pudieran usar a diario — para todo, desde procesar los palés entrantes hasta enviar pedidos o hacer seguimiento de incidencias.
Elegí Retool porque me permitió construir un frontend de ERP complejo y multimódulo en semanas en lugar de meses. El resultado: un ERP a medida con más de 10 módulos operativos:
- Módulo de pedidos — Vista en tiempo real de todos los pedidos de todos los marketplaces. Filtrado por estado, cuenta y fecha. Cambios de estado con un clic. Generación de etiquetas de envío
- Módulo de inventario — Ciclo de vida completo del artículo: entrada → categorización → publicación → vendido → enviado. Seguimiento de la ubicación dentro del almacén
- Módulo de facturación — Facturas autogeneradas a partir de los datos de ventas. Informes mensuales. Análisis de márgenes por palé y por marketplace
- Módulo de incidencias — Seguimiento de problemas de clientes con pedidos vinculados, flujos de resolución y patrones históricos
- Analítica de chats — Métricas de las conversaciones de Wallapop: tiempos de respuesta, embudos de conversión, señales de satisfacción del cliente
- Escáner móvil — Escaneo de códigos de barras para las operaciones de almacén. Los trabajadores escanean artículos para actualizar ubicaciones, marcarlos como enviados o señalar incidencias
El reto clave con Retool era que se sintiera nativo. Las apps de Retool por defecto parecen paneles de administración. Invertí un esfuerzo considerable en CSS personalizado, renderizado condicional y flujos de UX que resultaran intuitivos para trabajadores de almacén que nunca han usado software empresarial.
Fase 5: pipeline de enriquecimiento de productos con IA
Una de las partes que más tiempo consume del negocio es la creación de los anuncios de producto. Cada artículo necesita:
- Un título adecuado para el marketplace
- Una clasificación de categoría precisa
- Una descripción detallada que venda
- Un precio competitivo basado en datos de mercado
Escribir esto manualmente para miles de SKUs es una locura. A ~15 minutos por artículo, son más de 40 horas a la semana solo en descripciones. Así que construí un pipeline de IA:
- Scraper de Amazon — Identifica productos de nuestro inventario de palés en Amazon.es, extrae títulos, descripciones, características, imágenes y precios. Anti-detección con rotación de UA y limitación de peticiones para evitar bloqueos
- Enriquecimiento con GPT — Introduce los datos extraídos en GPT-4 con prompts estructurados. El modelo categoriza los artículos, genera títulos específicos para cada marketplace (el estilo de Wallapop es muy distinto del de eBay), redacta descripciones y sugiere precios
- Pipeline de imágenes — Descarga las imágenes de producto, aplica transformaciones anti-duplicado (OpenCV) para evitar los filtros de imágenes duplicadas de los marketplaces, y las redimensiona y comprime para una subida óptima
- Sincronización de anuncios — Envía los datos enriquecidos a cada marketplace con adaptaciones específicas de formato
El pipeline funciona de forma autónoma. Le paso un lote de artículos nuevos y, horas después, tengo anuncios totalmente enriquecidos listos para publicar en todos los marketplaces. Lo que antes ocupaba la semana entera de un empleado a jornada completa ahora se ejecuta en segundo plano mientras procesamos el siguiente palé.
Fase 6: el puente nube-local (el problema más difícil)
Aquí va un problema del que nadie habla en los blogs de arquitectura: ¿cómo imprimes una etiqueta de envío física desde una interfaz en la nube?
El frontend de nuestro ERP a medida corre en Retool Cloud. Nuestra impresora de etiquetas es una Brother QL-700 conectada por USB a un PC del almacén. No hay un camino nativo en la nube entre ambos. Necesitaba salvar esa distancia sin obligar al equipo de almacén a alternar entre aplicaciones.
La solución es lo que llamo el patrón Command Bridge:
- La interfaz de Retool escribe un registro de comando en PostgreSQL (p. ej., «imprimir etiqueta para el pedido #1234»)
- Un demonio Python local en el PC del almacén consulta si hay comandos nuevos cada pocos segundos
- Cuando encuentra uno, adquiere un bloqueo exclusivo de base de datos, procesa el comando (genera e imprime la etiqueta) y lo marca como completado
- La interfaz de Retool ve la actualización del estado y se la refleja al usuario
La parte delicada es la fiabilidad. ¿Qué pasa si el demonio local se cae? ¿Y si se ejecutan dos instancias a la vez? Implementé:
- Monitorización por heartbeat — El demonio escribe una marca de tiempo en cada ciclo. Si el heartbeat se detiene durante ~60 segundos, el sistema lo señala y puede reiniciarlo
- Bloqueo exclusivo — Los advisory locks de PostgreSQL evitan el procesamiento duplicado de comandos
- Conmutación por error automática — Si un comando se reclama pero no se completa dentro de la ventana de tiempo límite, se devuelve a la cola
Este patrón ahora gestiona no solo la impresión de etiquetas, sino cualquier operación que requiera la interacción con hardware local desde una interfaz en la nube.
Fase 7: sincronización multi-marketplace
Con el inventario en PostgreSQL, los anuncios enriquecidos por IA y los pedidos fluyendo a través de los extractores, la última pieza era mantenerlo todo sincronizado entre los marketplaces.
El motor de sincronización mantiene PostgreSQL como única fuente de verdad y envía los datos con el formato adecuado a cada plataforma:
- Wallapop — A través de la API obtenida por ingeniería inversa (formato propio, límites de caracteres, mapeo de categorías)
- eBay — A través de la Feed API oficial (autenticación OAuth2, cargas por lotes en CSV de más de 1.000 artículos)
- PortalHero — A través de su capa de integración (formato específico del marketplace)
Cuando un artículo se vende en una plataforma, el motor de sincronización lo retira de las demás en cuestión de minutos. Cuando actualizo un precio en el ERP, se propaga a todas partes. Cuando llega inventario nuevo, los anuncios se publican en todos los marketplaces simultáneamente.
La arquitectura completa
Visto en conjunto, el sistema completo tiene este aspecto:
Data Sources Processing Layer Core Outputs
───────────── ──────────────── ──── ───────
Wallapop API ──┐ ┌──────────┐
eBay API ──────┤ FastAPI Backend │PostgreSQL│ Custom ERP Frontend
Amazon Scraper ┤──→ ( extractors ) ──→ │25+ models│──→ ( Retool ERP )
PortalHero ────┤ ThreadPoolExecutor │35+ migr. │ 10+ modules
Google Drive ──┘ OpenAI GPT-4 └──────────┘
│
Command Bridge Pattern
(excl. lock + heartbeat)
│
Local Hardware
(Brother QL-700 printer)
Todos los componentes hablan con la misma API. Cada dato vive en la misma base de datos. Cada operación queda registrada, trazada y es recuperable.
Escala e impacto
Esto es lo que este sistema gestiona en producción, a diario:
| Métrica | Valor |
|---|---|
| Pedidos procesados/día | ~100+ |
| Cuentas de marketplace activas | 12 |
| Miembros del equipo que usan el ERP a diario | 6 |
| Marketplaces sincronizados | 3 (Wallapop, eBay, PortalHero) |
| Procesamiento manual de pedidos sustituido | ~5h/día |
| Creación manual de anuncios sustituida | ~40h/semana |
| APIs de marketplaces con ingeniería inversa | Wallapop, eBay |
| Módulos del ERP (Retool) | 10+ |
| Modelos de base de datos | 25+ |
| Migraciones de base de datos | 35+ |
| Versiones del extractor (Wallapop) | 5 principales |
Esto no es un proyecto de demostración. Es un sistema de producción que gestiona inventario real, dinero real y operaciones reales con clientes. Cada día. Construido y mantenido por un solo ingeniero.
Qué haría diferente
Tres años de iteración te enseñan mucho sobre tus propios errores:
- Empieza por la base de datos, no por los scripts. Primero construí los scripts de automatización y la base de datos después. Eso supuso meses de Google Sheets como intermediario, lo que generó problemas de integridad de datos que costó semanas limpiar
- Invierte antes en monitorización. Añadí el logging estructurado y los health checks tarde. Durante demasiado tiempo me fié del «si nadie se queja, probablemente funciona»
- No construyas la UI durante la migración. Construí el frontend del ERP a medida en Retool en paralelo a la migración de Sheets→PostgreSQL. Mi equipo vio interfaces a medio terminar durante la transición, lo que ralentizó la adopción
- Documenta la ingeniería inversa de la API sobre la marcha. Cuando Wallapop cambió su API, a veces tuve que volver a descubrir endpoints porque no había documentado bien el mapeo original
La conclusión
Construir un ERP de producción como ingeniero en solitario mientras gestionas el negocio que está diseñado para automatizar es un reto de ingeniería único. Eres a la vez el arquitecto, el desarrollador, el DBA, el QA, el ingeniero de DevOps y el product manager — además del CEO, el jefe de almacén y el responsable de atención al cliente.
El trabajo técnico es la parte fácil. La parte difícil es:
- Diseñar sistemas que compañeros no técnicos puedan usar sin formación
- Migrar datos de producción sin perder un solo pedido ni desbaratar los recuentos de inventario
- Mantener 12 sesiones de cuentas de marketplace que pueden romperse en cualquier momento
- Recuperarte de una inundación catastrófica que destruyó tu almacén y aun así volver más fuerte
- Sacar funcionalidades a las 2 de la madrugada porque el palé de mañana llega a las 8 y el equipo necesita el nuevo módulo
No lo cambiaría por nada. Así es la ingeniería de verdad — no código perfecto, sino código que resuelve problemas reales para personas reales, cada día.
Los componentes de la plataforma son de código abierto: github.com/AspiranteD/AspiranteD