Un seul ingénieur. Une plateforme entièrement sur mesure. 12 comptes places de marché. ~100 commandes/jour. 5 employés qui l'utilisent au quotidien. Voici l'histoire technique complète de la manière dont j'ai conçu, développé et exploité l'ensemble de la plateforme de production derrière REUSALIA — du premier bot Selenium à un ERP complet doté d'API rétro-conçues, de pipelines d'IA et d'une intégration matérielle physique.
Le problème : faire tourner une vraie entreprise sur des processus manuels
En avril 2023, j'ai fondé REUSALIA — une entreprise d'e-commerce qui achète des palettes de liquidation Amazon, traite les stocks et revend les articles à l'unité sur plusieurs places de marché (Wallapop, eBay, PortalHero). Le modèle économique est simple. Les opérations qui le sous-tendent ne le sont pas.
Chaque palette qui arrive contient 50 à 200 articles hétéroclites. Chaque article doit être inspecté, photographié, catégorisé, valorisé, mis en vente sur plusieurs plateformes, suivi jusqu'à la vente, emballé et expédié. Multipliez cela par des milliers de SKU répartis sur 12 comptes places de marché, et vous commencez à mesurer l'ampleur du problème.
À mes débuts, tout était manuel. Mettre en vente un seul article sur Wallapop prenait 5 à 10 minutes de saisie. Les commandes arrivaient via plusieurs comptes et devaient être vérifiées une par une. Les stocks étaient suivis dans des Google Sheets. Il n'y avait pas de système — juste une personne avec un ordinateur portable et un entrepôt.
Trois ans plus tard, toute l'activité repose sur une plateforme que j'ai construite de zéro : un back-end FastAPI avec plus de 25 modèles de base de données, un ERP Retool sur mesure comptant plus de 10 modules opérationnels, des API de places de marché rétro-conçues, un enrichissement de produits propulsé par l'IA et une passerelle matérielle sur mesure qui relie les interfaces cloud à des imprimantes d'étiquettes physiques. Voici comment tout cela a évolué.
Phase 1 : l'ère Selenium (2023)
Le premier problème technique que j'ai résolu était le plus pénible : la publication d'annonces sur Wallapop.
Wallapop ne dispose d'aucune API de publication en masse. Pas d'import CSV. Aucun moyen de mettre en vente des produits à grande échelle. Chaque annonce devait être créée manuellement via leur interface web — renseigner le titre, la description, la catégorie, le prix, téléverser les photos, indiquer la localisation, confirmer. À raison de 5 à 10 minutes par article, mettre en vente un catalogue de 500 à 600 articles était un travail à temps plein.
J'ai donc développé un bot Selenium qui automatisait tout le processus. Il ouvrait un navigateur, accédait au formulaire d'annonce, remplissait chaque champ, téléversait les images et validait. Chaque annonce prenait environ 1 minute (intentionnellement ralentie pour éviter la détection).
Mais 1 minute par article pour 600 articles représente tout de même 10 heures. Et je devais republier tous les 3 jours pour maintenir mon positionnement sur la place de marché. J'ai donc passé à l'échelle de la seule manière possible : horizontalement, sur plusieurs machines physiques.
J'ai installé 5 à 6 PC, connectés à distance à chacun via AnyDesk, et lancé plusieurs instances de bot par machine. Chaque instance utilisait des cookies et des user agents différents. Ainsi, je pouvais publier l'intégralité de mon catalogue en environ une heure. Tous les 3 jours, je consacrais une heure à gérer la flotte de bots distribuée.
C'était laid. C'était fragile. Ça marchait.
Ce que j'ai appris
- L'automatisation ne commence pas par l'élégance — elle commence par la réduction de la douleur
- Parfois, « passer à l'échelle » veut dire 6 ordinateurs portables sur un bureau, pas Kubernetes
- L'anti-détection compte dès le premier jour : rotation des user agents, randomisation du timing, isolation des sessions
Phase 2 : rétro-ingénierie de l'API privée de Wallapop (2023-2024)
À mesure que l'entreprise grandissait, la complexité opérationnelle aussi. Nous sommes passés de 10 commandes par jour à près de 100. D'un compte Wallapop à 12. L'approche Selenium ne tenait plus la charge — ni pour la publication, et encore moins pour la gestion des commandes.
Le problème, c'est que Wallapop est un écosystème fermé. Pas d'API publique. Pas de documentation. Aucune intégration tierce. Tout se passe à l'intérieur de leur application et de leur site web. Pour la plupart des gens, c'est un mur. Pour moi, c'était une invitation.
J'ai commencé à intercepter le trafic réseau. Pour chaque action que j'effectuais sur le site web — parcourir les annonces, consulter les commandes, lire les conversations — je capturais la requête HTTP, j'étudiais les en-têtes, je décodais les charges utiles et je cartographiais les structures de réponse.
Le processus de découverte
Rétro-concevoir une API privée, c'est un travail de détective :
- Capturer — Utiliser les DevTools du navigateur pour intercepter chaque requête au cours d'une session
- Classifier — Regrouper les requêtes par motif d'endpoint et méthode HTTP
- Décoder — Analyser les en-têtes de requête (en particulier l'autorisation), les paramètres de requête et les structures JSON des réponses
- Recouper — Comparer les réponses de différents comptes pour identifier ce qui est propre à l'utilisateur par rapport à ce qui est universel
- Reproduire — Construire un client Python capable de s'authentifier et d'effectuer les mêmes requêtes en dehors du navigateur
- Itérer — Quand Wallapop modifie son API (ce qui arrive), mettre à jour le client
Au fil de 5 versions majeures de la base de code de l'extracteur, j'ai cartographié leur système d'authentification (basé sur des cookies avec des bearer tokens), leurs endpoints de gestion des commandes, leur API de messagerie et leur système de métadonnées d'annonces. Le résultat : plus de 2 100 lignes de code Python de production capables de :
- Extracteur de commandes — Récupérer toutes les commandes sur les 12 comptes, normaliser les données et les injecter dans notre ERP. Ce seul script a remplacé l'équivalent d'environ 5 heures de travail manuel quotidien
- Extracteur de messagerie — Récupérer les données de conversation pour analyser les indicateurs de l'entonnoir de vente : temps de réponse, taux de conversion, comportements clients
- Extracteur d'annonces — Surveiller quels articles obtiennent le plus de vues, lesquels nécessitent un ajustement de prix, lesquels devraient être mis en avant
L'architecture multi-comptes a été la partie la plus difficile. Chaque compte a son propre cycle de vie d'authentification : les cookies expirent, les tokens doivent être rafraîchis, les sessions sont invalidées. J'ai construit un gestionnaire d'authentification centralisé qui stocke les identifiants dans PostgreSQL, rafraîchit automatiquement les tokens entre les sessions et fournit des contextes d'authentification propres à chaque extracteur.
Personne d'autre n'a construit cela. Il existe des outils comme PortalHero pour la publication en masse, mais rien pour l'extraction. Nos extracteurs sont uniques — et ce sont eux qui rendent possible l'exploitation d'une opération à 12 comptes avec une équipe de 5 personnes plutôt qu'une équipe d'opérations manuelles bien plus nombreuse.
Phase 3 : la plateforme cœur — FastAPI + PostgreSQL (2024-2025)
Avec les extracteurs qui alimentaient les données de manière fiable, il me fallait un endroit où ces données puissent vivre et quelque chose pour les exploiter. Google Sheets n'allait plus suffire (c'est toute une autre histoire).
J'ai conçu la plateforme cœur autour de trois principes :
- Source unique de vérité — Chaque donnée vit dans PostgreSQL. Pas de feuilles de calcul, pas de fichiers locaux, pas de « je le mettrai à jour plus tard »
- API-first — Chaque opération passe par le back-end FastAPI. Le front-end ERP sur mesure construit sur Retool, les extracteurs, les moteurs de synchronisation — tous dialoguent avec la même API
- Automatisation opérationnelle — Si un humain fait quelque chose plus de deux fois, cela devrait être automatisé
Conception de la base de données
Le schéma PostgreSQL compte plus de 25 modèles avec plus de 35 migrations, couvrant :
- Stocks — Articles, SKU, catégories, états, emplacements, photos
- Commandes — Suivi des commandes multi-places de marché avec workflows de statut
- Ventes & facturation — Suivi du chiffre d'affaires, analyse des coûts, calcul des marges par article et par palette
- Authentification — Stockage centralisé des identifiants pour tous les comptes places de marché
- Planification — Files de tâches pour les opérations automatisées (cycles de synchronisation, exécutions d'extraction)
- Incidents — Réclamations clients, retours, problèmes d'expédition
J'utilise SQLModel (SQLAlchemy + Pydantic) pour la couche ORM, ce qui me donne des modèles type-safe qui fonctionnent à la fois pour les opérations de base de données et la sérialisation de l'API. Alembic gère les migrations, et je n'ai jamais eu à en annuler une seule en production.
Architecture de l'API
Le back-end FastAPI expose ~60 endpoints couvrant les opérations CRUD, la logique métier et les intégrations. Décisions de conception clés :
- Injection de dépendances pour les sessions de base de données, l'authentification et la limitation de débit
- Tâches de fond pour les opérations lourdes (imports en masse, cycles de synchronisation)
- Gestion structurée des erreurs avec des codes d'erreur propres au métier
- Modèles de requête/réponse validés à la frontière de l'API — si de mauvaises données entrent, l'échec est bruyant et précoce
Phase 4 : l'ERP — front-end Retool (2025)
Une base de données et une API ne servent à rien si votre équipe ne peut pas interagir avec elles. Il me fallait une interface que 6 employés non techniciens puissent utiliser au quotidien — pour tout, du traitement des palettes entrantes à l'expédition des commandes en passant par le suivi des incidents.
J'ai choisi Retool parce qu'il m'a permis de construire un front-end ERP complexe et multi-module en quelques semaines plutôt qu'en quelques mois. Le résultat : un ERP sur mesure comptant plus de 10 modules opérationnels :
- Module Commandes — Vue en temps réel de toutes les commandes sur toutes les places de marché. Filtrage par statut, compte, date. Transitions de statut en un clic. Génération d'étiquettes d'expédition
- Module Stocks — Cycle de vie complet de l'article : réception → catégorisation → mise en vente → vendu → expédié. Suivi des emplacements au sein de l'entrepôt
- Module Facturation — Factures générées automatiquement à partir des données de vente. Reporting mensuel. Analyse des marges par palette et par place de marché
- Module Incidents — Suivi des problèmes clients avec commandes liées, workflows de résolution et tendances historiques
- Analytique des conversations — Indicateurs des conversations Wallapop : temps de réponse, entonnoirs de conversion, signaux de satisfaction client
- Scanner mobile — Lecture de codes-barres pour les opérations d'entrepôt. Les employés scannent les articles pour mettre à jour les emplacements, marquer comme expédié ou signaler des problèmes
Le principal défi avec Retool était de lui donner une impression native. Les applications Retool par défaut ressemblent à des panneaux d'administration. J'ai investi des efforts considérables dans du CSS personnalisé, du rendu conditionnel et des parcours UX intuitifs pour des employés d'entrepôt qui n'ont jamais utilisé de logiciel d'entreprise.
Phase 5 : pipeline d'enrichissement produit par IA
L'une des parties les plus chronophages de l'activité est la création des annonces produit. Chaque article nécessite :
- Un titre adapté à la place de marché
- Une classification de catégorie précise
- Une description détaillée qui vend
- Un prix compétitif basé sur les données du marché
Rédiger tout cela manuellement pour des milliers de SKU est insensé. À raison de ~15 minutes par article, cela représente plus de 40 heures par semaine rien que pour les descriptions. J'ai donc construit un pipeline d'IA :
- Scraper Amazon — Identifie les produits de notre stock de palettes sur Amazon.es, extrait les titres, descriptions, caractéristiques, images et prix. Anti-détection avec rotation des UA et étranglement des requêtes pour éviter les blocages
- Enrichissement GPT — Alimente les données scrapées dans GPT-4 avec des prompts structurés. Le modèle catégorise les articles, génère des titres spécifiques à chaque place de marché (le style Wallapop est très différent du style eBay), rédige les descriptions et suggère les prix
- Pipeline d'images — Télécharge les images produit, applique des transformations anti-doublon (OpenCV) pour contourner les filtres d'images dupliquées des places de marché, redimensionne et compresse pour un téléversement optimal
- Synchronisation des annonces — Pousse les données enrichies vers chaque place de marché avec des adaptations propres à chaque format
Le pipeline tourne de manière autonome. Je lui fournis un lot de nouveaux articles, et quelques heures plus tard j'ai des annonces entièrement enrichies, prêtes à être publiées sur toutes les places de marché. Ce qui prenait une semaine entière à un employé à temps plein tourne désormais en arrière-plan pendant que nous traitons la palette suivante.
Phase 6 : la passerelle cloud-local (le problème le plus difficile)
Voici un problème dont personne ne parle dans les blogs d'architecture : comment imprimer une étiquette d'expédition physique depuis une interface cloud ?
Notre front-end ERP sur mesure tourne sur Retool Cloud. Notre imprimante d'étiquettes est une Brother QL-700 connectée en USB à un PC d'entrepôt. Il n'existe aucun chemin cloud-native entre les deux. Je devais combler ce fossé sans obliger l'équipe d'entrepôt à jongler entre les applications.
La solution est ce que j'appelle le patron Command Bridge :
- L'interface Retool écrit un enregistrement de commande dans PostgreSQL (par ex. « imprimer l'étiquette pour la commande #1234 »)
- Un daemon Python local sur le PC d'entrepôt interroge les nouvelles commandes toutes les quelques secondes
- Lorsqu'il en trouve une, il acquiert un verrou exclusif en base de données, traite la commande (génère et imprime l'étiquette) et la marque comme terminée
- L'interface Retool voit la mise à jour du statut et la reflète à l'utilisateur
La partie délicate, c'est la fiabilité. Que se passe-t-il si le daemon local plante ? Et si deux instances tournent simultanément ? J'ai mis en place :
- Surveillance par heartbeat — Le daemon écrit un horodatage à chaque cycle. Si le heartbeat s'arrête pendant ~60 secondes, le système le signale et peut redémarrer
- Verrouillage exclusif — Les verrous consultatifs de PostgreSQL empêchent le traitement en double des commandes
- Basculement automatique — Si une commande est réclamée mais non terminée dans le délai imparti, elle est remise dans la file
Ce patron gère désormais non seulement l'impression d'étiquettes, mais toute opération nécessitant une interaction avec du matériel local depuis une interface cloud.
Phase 7 : synchronisation multi-places de marché
Avec les stocks dans PostgreSQL, les annonces enrichies par l'IA et les commandes circulant via les extracteurs, la dernière pièce consistait à maintenir tout synchronisé entre les places de marché.
Le moteur de synchronisation maintient PostgreSQL comme source unique de vérité et pousse les données formatées vers chaque plateforme :
- Wallapop — Via l'API rétro-conçue (format personnalisé, limites de caractères, mappage de catégories)
- eBay — Via la Feed API officielle (authentification OAuth2, imports CSV par lots de plus de 1 000 articles)
- PortalHero — Via leur couche d'intégration (formatage propre à la place de marché)
Lorsqu'un article se vend sur une plateforme, le moteur de synchronisation le retire des autres en quelques minutes. Lorsque je mets à jour un prix dans l'ERP, il se propage partout. Lorsqu'un nouveau stock arrive, les annonces partent simultanément vers toutes les places de marché.
L'architecture complète
En prenant du recul, le système complet ressemble à ceci :
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)
Chaque composant dialogue avec la même API. Chaque donnée vit dans la même base de données. Chaque opération est journalisée, suivie et récupérable.
Échelle & impact
Voici ce que ce système gère en production, au quotidien :
| Indicateur | Valeur |
|---|---|
| Commandes traitées/jour | ~100+ |
| Comptes places de marché actifs | 12 |
| Membres de l'équipe utilisant l'ERP au quotidien | 6 |
| Places de marché synchronisées | 3 (Wallapop, eBay, PortalHero) |
| Traitement manuel des commandes remplacé | ~5 h/jour |
| Création manuelle d'annonces remplacée | ~40 h/semaine |
| API de places de marché rétro-conçues | Wallapop, eBay |
| Modules ERP (Retool) | 10+ |
| Modèles de base de données | 25+ |
| Migrations de base de données | 35+ |
| Versions de l'extracteur (Wallapop) | 5 majeures |
Ce n'est pas un projet de démonstration. C'est un système de production qui gère de vrais stocks, de l'argent réel et de véritables opérations clients. Tous les jours. Construit et maintenu par un seul ingénieur.
Ce que je ferais différemment
Trois ans d'itérations vous en apprennent beaucoup sur vos propres erreurs :
- Commencer par la base de données, pas par les scripts. J'ai d'abord construit les scripts d'automatisation et la base de données ensuite. Cela a signifié des mois de Google Sheets comme intermédiaire, ce qui a créé des problèmes d'intégrité des données dont le nettoyage a pris des semaines
- Investir plus tôt dans la supervision. J'ai ajouté la journalisation structurée et les health checks tardivement. Pendant trop longtemps, je me suis appuyé sur le « si personne ne se plaint, c'est que ça marche probablement »
- Ne pas construire l'interface pendant la migration. J'ai construit le front-end ERP sur mesure sur Retool en parallèle de la migration Sheets→PostgreSQL. Mon équipe a vu des interfaces à moitié finies pendant la transition, ce qui a ralenti l'adoption
- Documenter la rétro-ingénierie de l'API au fur et à mesure. Quand Wallapop a modifié son API, j'ai parfois dû redécouvrir des endpoints parce que je n'avais pas suffisamment documenté le mappage initial
À retenir
Construire un ERP de production en tant qu'ingénieur solo tout en faisant tourner l'entreprise qu'il est censé automatiser est un défi d'ingénierie unique. Vous êtes simultanément l'architecte, le développeur, le DBA, le QA, l'ingénieur DevOps et le chef de produit — en plus du PDG, du responsable d'entrepôt et du responsable du support client.
Le travail technique est la partie facile. La partie difficile, c'est :
- Concevoir des systèmes que des coéquipiers non techniciens peuvent utiliser sans formation
- Migrer des données de production sans perdre une seule commande ni fausser les comptages de stock
- Maintenir 12 sessions de comptes places de marché qui peuvent se rompre à tout moment
- Se remettre d'une inondation catastrophique qui a détruit votre entrepôt, et revenir plus fort malgré tout
- Livrer des fonctionnalités à 2 h du matin parce que la palette de demain arrive à 8 h et que l'équipe a besoin du nouveau module
Je n'échangerais cela pour rien au monde. Voilà à quoi ressemble la véritable ingénierie — non pas du code parfait, mais du code qui résout de vrais problèmes pour de vraies personnes, chaque jour.
Les composants de la plateforme sont open-source : github.com/AspiranteD/AspiranteD