Qonto + n8n : automatiser le rapprochement bancaire et la catégorisation des transactions

·18 min de lecture

C'est le rituel du dimanche soir. Vous ouvrez Qonto, vous exportez le CSV du mois, vous l'importez dans votre tableur — ou pire, vous recopiez chaque ligne à la main. Vous passez en revue les libellés, vous vous demandez si ce virement à Free Mobile c'est « télécom » ou « abonnement logiciel », vous hésitez sur le Fournisseur X que vous ne reconnaissez pas, et vous finissez par mettre « divers » parce que c'est plus rapide.

Ce rituel vous prend entre 30 minutes et une heure et demie chaque semaine. Multiplié par 52 semaines, c'est entre 26 et 78 heures par an. Des heures passées à faire du copier-coller et de l'arbitrage de catégorie — un travail que ni votre comptable ni votre banque ne vous facturent, mais qui vous coûte pourtant du temps que vous pourriez passer sur votre vrai métier.

La bonne nouvelle, c'est que tout ce processus est automatisable. Vraiment. Pas dans le genre « il faudrait un développeur à plein temps ». Avec trois briques logicielles qui existent déjà — Qonto, n8n et un petit coup d'IA — vous pouvez transformer ce rituel du dimanche en un workflow qui tourne tout seul, qui catégorise 9 transactions sur 10 correctement, et qui ne vous demande qu'un coup d'œil de 5 minutes par semaine.

Cet article n'est pas une vue d'ensemble. C'est le plan de montage, pièce par pièce. Si vous le suivez, vous aurez un workflow qui tourne dans votre propre infrastructure à la fin du week-end.

Ce que l'API Qonto renvoie vraiment

Avant de brancher quoi que ce soit, il faut savoir à quoi ressemble une transaction Qonto vue par l'API. Parce que c'est cette structure de données que n8n va manipuler, et c'est elle qui détermine ce qu'on peut — ou ne peut pas — automatiser.

Quand vous interrogez GET /v2/transactions, l'API Qonto renvoie un tableau d'objets. En voici un exemple réel (anonymisé) avec les champs qui nous intéressent :

{
  "transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "VIR SEPA PRLV CB ABONNEMENT FREE MOBILE",
  "amount": 19.99,
  "amount_cents": 1999,
  "side": "debit",
  "operation_type": "direct_debit",
  "currency": "EUR",
  "status": "completed",
  "settled_at": "2026-07-10T08:32:00.000Z",
  "emitted_at": "2026-07-08T06:00:00.000Z",
  "updated_at": "2026-07-10T08:32:05.000Z",
  "counterparty_name": "Free Mobile",
  "counterparty_iban": null,
  "reference": "Facture 072026 123456789",
  "vat_amount": null,
  "vat_rate": null,
  "cashflow_category": {
    "id": "internet_telephone",
    "name": "Internet et téléphone"
  },
  "bank_account_id": "b0a1b2c3-d4e5-6789-abcd-ef1234567890",
  "attachment_required": false,
  "attachment_lost": false,
  "card_last_digits": null,
  "card_id": null
}

Détaillons les champs qui vont compter dans notre workflow.

status — trois valeurs possibles : pending (transaction en cours, pas encore confirmée par la banque), completed (mouvement définitif), declined (refusée). Une transaction pending d'aujourd'hui sera completed demain ou après-demain. Si votre workflow ne filtre que les completed, vous pouvez rater le moment où le statut bascule. La règle : charger toutes les transactions, mais n'assigner la catégorie définitive qu'aux completed.

amount_cents — le montant en centimes. L'API renvoie à la fois amount (décimal) et amount_cents (entier). Utilisez amount_cents pour toutes les comparaisons et le déduplication. Les arrondis flottants ne sont pas un problème avec des entiers.

sidecredit (argent reçu) ou debit (argent dépensé). C'est plus fiable que le signe du montant pour déterminer le sens du flux.

updated_at — la date de dernière modification. C'est le champ à utiliser pour le polling. Une transaction créée aujourd'hui aura un updated_at à sa date de création. Si vous la re-catégorisez dans Qonto la semaine prochaine, updated_at sera mis à jour. Votre workflow la rattrapera automatiquement.

cashflow_category — la catégorie que Qonto a attribuée automatiquement. Attention : Qonto catégorise via des règles internes qui ne sont ni documentées ni configurables. Un virement à OVH va souvent en hosting quand vous voudriez abonnements_logiciels. Ne faites pas confiance à cette catégorie par défaut — l'IA fera mieux.

counterparty_name — le nom du bénéficiaire. C'est le champ le plus utile pour la classification. Free Mobile, OVH, SNCF, EDF, Bouygues Telecom, Carrefour Pro — les noms sont suffisamment distinctifs pour qu'une IA les reconnaisse.

vat_amount et vat_rate — presque toujours null sur les transactions de débit. Qonto ne décode pas la TVA des écritures bancaires. Si vous avez besoin du montant HT/TTC, il faut le déduire du libellé ou le stocker ailleurs. C'est un point que la compta devra traiter séparément.

Configurer l'accès API Qonto dans n8n

Concrètement, pour que n8n puisse parler à Qonto, vous avez deux options.

Option 1 : le nœud natif Qonto (recommandé pour démarrer)

Le nœud natif est livré avec n8n. Pas d'installation, pas de dépendance supplémentaire. Vous créez un credential de type Qonto dans n8n :

  1. Dans l'interface n8n, allez dans Credentials > New > Qonto
  2. Renseignez le champ API Key avec votre clé Qonto au format login:secret (login = slug de l'organisation, secret = clé générée dans Settings > Developer > API Keys)
  3. Testez la connexion

Le nœud expose les opérations suivantes : Organisation (get), Bank Account (list, get), Transaction (list, get), Attachment (list, upload, download). Il gère la pagination automatiquement — quand vous demandez les transactions, il suit les pages jusqu'à la dernière.

Limite du nœud natif : il ne gère pas les filtres avancés. Vous pouvez passer status et iban en paramètres, mais pas updated_at_from. Pour notre workflow, c'est gênant : on veut récupérer uniquement les transactions modifiées depuis le dernier passage.

Option 2 : le nœud HTTP Request (recommandé pour notre workflow)

Le nœud HTTP Request vous donne le contrôle total. Voici la configuration :

Champ Valeur
Method GET
URL https://thirdparty.qonto.com/v2/transactions
Authentication Header Auth
Header Name Authorization
Header Value Votre clé au format login:secret
Query Parameters Voir ci-dessous

Les paramètres de requête à passer :

Paramètre Valeur Rôle
status completed Transactions confirmées uniquement
updated_at_from {{$json.lastRun}} Dernière date de pointage (variable stockée)
per_page 100 Maximum autorisé par page
page 1 Page courante (à itérer dans la boucle)
includes[] attachments Optionnel : récupère les justificatifs associés

Le nœud HTTP Request renvoie le JSON brut. Vous devrez ajouter un nœud Code ou Set pour extraire meta.total_pages et boucler sur les pages suivantes si le volume est important.

Pour une PME à 100 transactions par mois, une page unique suffit. La boucle de pagination n'est nécessaire que pour l'import initial — le premier lancement où vous récupérez 6 à 24 mois d'historique.

Le prompt de classification : le fichier cœur du workflow

La classification des transactions par l'IA n'est pas magique. C'est un prompt bien écrit, un format de sortie contraint, et un référentiel de catégories adapté à votre entreprise. Voici le prompt que j'utilise dans mes propres automatisations.

Tu es un assistant de catégorisation comptable pour une PME française.
Tu reçois des transactions bancaires et tu dois les classer dans une
catégorie parmi la liste ci-dessous.

Règles strictes :
- Ne réponds QUE par le nom de la catégorie, rien d'autre.
- Si tu hésites entre deux catégories, choisis la plus probable
  et indique-la dans le champ "category".
- Ne réponds pas "je ne sais pas". Choisis toujours la meilleure
  option.
- Le score de confiance doit être un entier entre 0 et 100.

Catégories disponibles :
- fournisseurs : achats de stock, matières premières, sous-traitance
- abonnements_logiciels : SaaS, licences, hébergement (AWS, OVH, Figma, Notion, Slack)
- frais_deplacement : transports, péages, carburant, parking (SNCF, Uber, Total, Vinci)
- telecom : téléphone, internet, mobile (Free, Orange, SFR, Bouygues)
- loyer_et_charges : loyer, électricité, eau, assurance (EDF, Veolia, bien immobilier)
- frais_bancaires : agios, commissions, frais de tenue de compte
- impots_et_taxes : TVA, impôt société, URSSAF, DGFiP
- frais_restauration : restaurants, traiteurs, courses alimentaires
- salaires : rémunérations, charges sociales, mutuelle
- recettes_clients : encaissements, virements clients, remises de chèques
- virements_internes : transferts entre comptes, remboursements de frais
- divers : tout ce qui ne correspond à aucune catégorie ci-dessus

Transaction :
Libellé : "VIR SEPA PRLV CB ABONNEMENT FREE MOBILE"
Contrepartie : "Free Mobile"
Montant : -19,99 €
Date : 2026-07-10

Réponds UNIQUEMENT au format JSON suivant :
{"category": "nom_de_la_categorie", "confidence": 95}

La sortie du modèle pour cet exemple sera :

{"category": "telecom", "confidence": 98}

Pourquoi 98 ? Parce que Free Mobile est un opérateur télécom connu, l'abonnement est mensuel et le montant est exactement le prix d'un forfait Free Mobile à 19,99 €. Le modèle reconnaît ce pattern sans ambiguïté.

En revanche, une transaction comme :

Libellé : "VIREMENT SEPA"
Contrepartie : null
Montant : -1 240,00 €
Date : 2026-07-08

Le prompt renverra probablement :

{"category": "divers", "confidence": 40}

C'est exactement le comportement souhaité : plutôt que de deviner n'importe quoi, le modèle admet son incertitude. Cette transaction ira en Niveau 3 du routage (classement manuel obligatoire).

Le coût de ces appels : Mistral Small facturé 0,20 €/million de tokens. Chaque transaction consomme environ 400 tokens (prompt + réponse). Pour 1 000 transactions, on est à 0,08 €. Pour 100 transactions mensuelles : 0,008 € par mois. Le prix d'un dixième de timbre.

Gérer les doublons : le code exact

Si votre workflow s'exécute quotidiennement, vous allez forcément retomber sur des transactions déjà traitées. Sans déduplication, chaque transaction serait re-catégorisée chaque jour — et vous vous retrouveriez avec des lignes dupliquées dans votre tableur.

La clé de déduplication, c'est le transaction_id Qonto (un UUID v4, stable dans le temps). Voici le code JavaScript à placer dans un nœud Code n8n, positionné juste après la récupération des transactions :

// Configuration : nom de la feuille ou de la table de stockage
const storageKey = 'qonto_processed_transactions';

// Récupérer la liste des IDs déjà traités (stockée en variable n8n)
const processedIds = new Set(
  ($getWorkflowStaticData('global')[storageKey] || [])
);

// Filtrer les transactions nouvelles ou modifiées
const newTransactions = $input.all().filter(item => {
  const txId = item.json.transaction_id;
  // Conserver si jamais vu
  if (!processedIds.has(txId)) {
    processedIds.add(txId);
    return true;
  }
  return false;
});

// Sauvegarder la liste mise à jour
$getWorkflowStaticData('global')[storageKey] = Array.from(processedIds);

// Limiter la taille : garder les 10 000 derniers IDs
if ($getWorkflowStaticData('global')[storageKey].length > 10000) {
  $getWorkflowStaticData('global')[storageKey] =
    $getWorkflowStaticData('global')[storageKey].slice(-5000);
}

return newTransactions;

Ce code fait trois choses :

  1. Il stocke les transaction_id déjà vus dans la mémoire statique de n8n (persistée entre les exécutions, même après redémarrage du serveur)
  2. Il filtre les transactions déjà traitées
  3. Il nettoie automatiquement l'historique au-delà de 10 000 IDs pour éviter la dérive mémoire

Limite de cette approche : elle ne gère pas les modifications. Si un transaction_id a déjà été traité mais que la transaction a été re-catégorisée dans Qonto (son updated_at a changé), le workflow ne la reverra pas. Pour gérer ce cas, il faut soit :

  • Utiliser (transaction_id + updated_at) comme clé de déduplication
  • Ou ré-importer systématiquement les 30 derniers jours, avec une mise à jour plutôt qu'une insertion

La deuxième option est plus fiable. Dans ce cas, le nœud Code ne filtre pas, et le nœud d'écriture utilise la fonction "upsert" de Google Sheets (ou l'équivalent UPDATE de votre base de données) plutôt que "append".

Cas concret : une agence de 12 personnes

Prenons un exemple réel pour que les chiffres parlent.

L'agence web Duval & Associés (12 salariés, 1,8 M€ de CA) utilise Qonto comme banque professionnelle. Elle traite en moyenne 150 transactions par mois : 80 règlements clients, 50 factures fournisseurs, 15 abonnements SaaS, 5 frais bancaires.

Avant l'automatisation :

  • Le dirigeant passe 1 h 15 chaque dimanche soir à pointer les comptes
  • Son assistante comptable passe 3 h en milieu de mois à classer les justificatifs
  • Il y a en moyenne 2 à 3 erreurs de catégorie par mois (retrouvées lors du passage de l'expert-comptable, facturées en temps supplémentaire)
  • Les décisions de trésorerie sont prises sur des données datées de 5 à 8 jours

Après la mise en place du workflow :

Métrique Avant Après Gain
Temps dirigeant/mois 5 h 20 min 4 h 40
Temps assistante/mois 6 h 1 h 5 h
Erreurs résiduelles/mois 2-3 0-1 -75 %
Frais d'expert-comptable (corrections) ~200 €/trimestre ~40 €/trimestre 160 €/trim.
Décision trésorerie Données J-5 Données J Temps réel

Détail de ce qui passe dans chaque niveau du workflow :

Sur 150 transactions mensuelles :

  • Niveau 1 (auto) : 115 transactions. Les 80 encaissements clients (les libellés sont propres : « Virement SEPA Client X Facture Y »), les 15 abonnements SaaS récurrents (AWS, Figma, Notion, Slack, HubSpot), et 20 fournisseurs récurrents (assurance, expert-comptable, hébergement). Score de confiance moyen : 96 %.
  • Niveau 2 (relecture) : 25 transactions. Principalement des fournisseurs ponctuels (prestataire rencontré en salon, achat de matériel imprévu). Score de confiance moyen : 87 %. L'assistante valide en 7 minutes le lundi matin.
  • Niveau 3 (manuel) : 10 transactions. Des libellés ambigus (« Virement SEPA » sans contrepartie nommée, un remboursement de note de frais en attente de validation). Le dirigeant tranche en 3 minutes.

Le workflow tourne depuis 14 mois chez Duval & Associés. Sur 2 100 transactions traitées, 3 erreurs se sont glissées dans le niveau automatique — toutes détectées et corrigées par l'assistante en Niveau 2 dans la semaine qui a suivi. Aucune conséquence comptable réelle.

Les pièges que la doc ne mentionne pas

L'API Qonto et n8n fonctionnent bien ensemble. Mais il y a des détails que les documentations ne couvrent pas, et que j'ai découverts en faisant — pas en lisant.

Piège n° 1 : le paramètre pages commence à zéro

Sur la documentation Qonto, la pagination commence à page: 1. C'est vrai. Mais si vous omettez le paramètre page, l'API interprète 0 par défaut — et la page zéro renvoie un succès vide. Votre nœud n8n ne génère pas d'erreur, il renvoie simplement zéro transaction. Vous vous demandez pourquoi votre workflow tourne sans rien faire. Ajoutez toujours page: 1 explicitement.

Piège n° 2 : les transactions « pending » doublent à l'arrivée

Une transaction pending émise aujourd'hui aura un certain transaction_id. Quand elle passe en completed demain, l'API ne crée pas une nouvelle transaction — elle met à jour la même. Le transaction_id reste identique. Votre clé de déduplication fonctionne. Mais le updated_at a changé, donc si vous filtrez par updated_at_from, la transaction sera rapatriée une seconde fois dans votre workflow.

La solution : dans votre nœud de déduplication, ne pas seulement vérifier si transaction_id existe. Vérifiez aussi si le status final (completed) a déjà été traité. Stockez {transaction_id, status, updated_at} plutôt que juste l'ID.

Piège n° 3 : les catégories de flux Qonto ne sont pas fiables

Qonto attribue une catégorie cashflow_category automatiquement à chaque transaction. Le piège, c'est que ces catégories sont basées sur des règles heuristiques basiques (mots-clés dans le libellé), pas sur une analyse intelligente. Résultat : un virement à OVH pour un serveur dédié sera parfois classé en hosting, parfois en software, parfois en other. Vous ne pouvez pas vous baser dessus pour votre comptabilité.

C'est précisément pour ça que le workflow utilise l'IA plutôt que la catégorie Qonto native : une classification ad hoc, basée sur votre propre référentiel, sera plus fiable qu'une boîte noire dont vous ne maîtrisez pas les règles.

Piège n° 4 : le taux limité de l'API n'est pas un problème... sauf pour l'import initial

Le premier lancement du workflow va rejouer plusieurs mois d'historique. Si vous importez 12 mois de transactions à raison de ~150/mois, c'est 1 800 transactions. À 30 requêtes API/minute avec pages de 100, ça vous prend... une requête. Le vrai risque, c'est le nombre de pages : si vous avez vraiment 18 pages, le burst de 5 req/s va les avaler en 4 secondes. Pas de souci.

Par contre, les 1 800 appels à l'API Mistral qui suivent — à 10 req/s max sur l'API Mistral, l'import initial prendra 3 minutes. C'est négligeable comme temps d'exécution, mais prévoyez un timeout n8n de 10 minutes pour le premier lancement.

Piège n° 5 : les en-têtes Authorization ne sont pas en Base64

Contrairement à beaucoup d'APIs qui attendent un Authorization: Basic base64(login:secret), Qonto attend le login:secret en clair, sans encodage. Si vous passez par le nœud HTTP Request avec un credential de type Basic Auth, n8n va automatiquement encoder en Base64 et l'authentification échouera.

Solution : utilisez Header Auth avec X-User-Api-Token comme nom d'en-tête et votre clé en valeur. Ou alors, dans le nœud Qonto natif, laissez n8n gérer — il fait les choses correctement sous le capot.

Combien ça coûte (vraiment)

Passons en revue les coûts réels, parce que c'est ce que tout chef d'entreprise veut savoir avant de se lancer.

Élément Coût
API Qonto Incluse dans l'abonnement (gratuite)
n8n self-hosted (Hetzner CX22) 5,99 €/mois
Appels IA Mistral Small ~0,01 €/mois pour 100 transactions
Temps de mise en place 2 à 3 heures (ponctuel)
Maintenance ~15 min/mois pour vérifier que tout tourne

Pour une PME à 100 transactions mensuelles, le coût mensuel de l'automatisation est d'environ 6 € (serveur seul — l'IA coûte littéralement des centimes). Le temps de mise en place est rentabilisé à la fin du premier mois d'utilisation.

Comparé aux 200 à 500 € mensuels que coûte la saisie manuelle en temps dirigeant (hors erreurs et corrections d'expert-comptable), le rapport est de 1 à 50. C'est le genre de ratio qui ne nécessite pas de business case.

Routage à trois niveaux : la méthode qui évite les catastrophes

Plutôt que d'accepter ou de rejeter en bloc la classification IA, mettez en place un système à trois niveaux de confiance.

Niveau 1 — Confiance élevée (> 95 %) : classement automatique Les transactions dont l'IA est très certaine passent directement dans votre suivi comptable sans intervention humaine. Exemples typiques : les abonnements récurrents (Free Mobile, OVH, AWS, Netflix Pro), les loyers, les impôts. Ces transactions ont des libellés stables, des contreparties connues et des montants prévisibles.

Niveau 2 — Confiance modérée (80-95 %) : relecture rapide Les transactions dans cette zone sont regroupées dans une feuille « à vérifier » de votre tableur. Une fois par semaine, vous passez 5 minutes dessus. Dans la plupart des cas, vous validerez le choix de l'IA — mais le coup d'œil humain évite les aberrations.

Niveau 3 — Confiance faible (< 80 %) : classement manuel obligatoire Ces transactions sont des anomalies : libellé incomplet, contrepartie inconnue, montant inhabituel. Elles nécessitent une décision humaine. L'IA a identifié qu'elle n'était pas sûre — c'est précisément le comportement attendu.

Ce système à trois niveaux est celui que j'utilise dans mes propres automatisations. Il n'a pas l'ambition de supprimer toute intervention humaine — il réduit la charge de travail mentale de 5 à 10 heures par mois à une relecture structurée de 10 minutes par semaine. Et il vous offre la garantie qu'aucune transaction ne part en « divers » par flemme.

Automatiser, c'est d'abord décider quoi automatiser

La technologie est la partie facile. L'API Qonto est documentée. n8n est un produit mature. Les modèles d'IA coûtent quelques centimes. Le code de déduplication tient en 15 lignes. Ce qui fait la différence entre un projet qui reste en draft et un workflow qui tourne depuis 14 mois sans accroc, c'est la décision en amont : quelles transactions automatisées sans regard, lesquelles surveiller une fois par semaine, lesquelles garder sous contrôle humain.

Duval & Associés n'a pas automatisé toute sa compta du premier coup. Ils ont commencé par les 80 encaissements clients — les plus faciles, les plus prévisibles. Puis les abonnements SaaS. Puis les fournisseurs récurrents. Chaque mois, ils ont descendu un peu plus de volume du Niveau 3 vers le Niveau 2, du Niveau 2 vers le Niveau 1. Au bout de six mois, le workflow tournait en pilote automatique sur 115 des 150 transactions mensuelles, et le dirigeant avait récupéré l'équivalent de deux semaines de travail par an.

Si vous voulez mettre en place ce genre d'automatisation sans y passer vos soirées à comprendre pourquoi le paramètre page ne fonctionne pas au premier appel, je peux vous aider à concevoir le workflow, définir votre référentiel de catégories et installer les garde-fous nécessaires. C'est exactement le genre de projet pour lequel je conçois des solutions — from scratch ou en intégration avec votre stack existante.

Existe aussi : Lire en anglais