TL;DR
- Chaque facture PDF reçue dans Gmail est lue, analysée par l’IA et ajoutée à ton registre Google Sheets.
- Fournisseur, n° de facture, date, HT, TVA, TTC, devise et catégorie : 9 champs extraits.
- Devis, PDF scannés et cas douteux partent dans un libellé « à vérifier », sans rien écrire.
- Testé sur 5 vrais PDF : 3 factures exactes, 2 faux positifs évités, zéro doublon.
- Coût IA mesuré : 0,00034 $ par facture.
Fin du mois. Ton comptable te réclame le détail de tes achats. Tu ouvres Gmail, tu tapes « facture », et tu recopies : Notion 10 $, OVH 14,39 €, Canva 110 €… Il en manque forcément une, celle qui est arrivée dans un fil de discussion avec un sous-traitant.
Le problème n’est pas la difficulté, c’est la répétition. Lire un PDF, repérer le total, la TVA et le numéro : une IA sait faire ça très bien, pour une fraction de centime.
On va construire un workflow n8n qui surveille ta boîte, lit chaque facture PDF et remplit ton registre des achats tout seul. Il sait aussi reconnaître ce qui n’est pas une facture. Je l’ai testé sur de vrais PDF, avec un vrai Google Sheet : les chiffres de cet article viennent de ces exécutions.
La saisie de factures, ce boulot que personne ne veut
Camille est freelance. Elle reçoit entre 15 et 25 factures d’achat par mois : abonnements SaaS américains sans TVA, hébergeur français avec TVA, sous-traitants qui envoient leur PDF en pièce jointe. Elle tient un Google Sheet pour son comptable, qu’elle remplit… quand elle y pense.
Les logiciels de comptabilité savent lire des justificatifs. Mais si tu es en micro-entreprise, ou si ton comptable te demande juste un tableau, tu n’as pas envie de payer un abonnement pour ça. Les tutos qui existent partent souvent d’un dossier Google Drive. Or tes factures arrivent par email, et c’est là que le travail de tri commence.
Le vrai défi n’est pas d’extraire un montant. C’est de ne pas écrire n’importe quoi dans ton registre : un devis pris pour une facture, un scan illisible transformé en montant inventé, la même facture comptée deux fois. Ce workflow est construit autour de ces trois risques.
Ce qu’on construit
Toutes les heures, n8n cherche dans Gmail les emails avec un PDF qui parlent de facture, de reçu ou d’invoice. Pour chacun, il lit le texte du PDF, demande à l’IA d’en extraire les données, vérifie que c’est bien une facture, puis l’ajoute au registre. L’email reçoit un libellé pour ne jamais être traité deux fois.

9 nœuds, plus le modèle d’IA. Trois choix structurent le tout :
- L’IA ne lit que le texte du PDF. Pas l’objet de l’email, qui ment souvent (« Votre devis (facture à suivre) »).
- Le doute part en vérification. Si ce n’est pas clairement une facture avec un montant, rien n’est écrit, et l’email reçoit le libellé
compta-a-verifier. - Chaque facture a une clé unique. Fournisseur + numéro de facture. Rejouer le workflow met à jour la ligne au lieu de la dupliquer.
Ce qu’il te faut
| Élément | À quoi ça sert | Coût |
|---|---|---|
| n8n (cloud ou auto-hébergé) | Faire tourner le workflow | Starter : 20 €/mois en annuel pour 2 500 exécutions. Auto-hébergé : gratuit hors serveur |
| Gmail | Recevoir les factures | Gratuit |
| Google Sheets | Le registre des achats | Gratuit |
| Une clé API Gemini (Google AI Studio) | Extraire les données | Palier gratuit, ou 0,25 $ / 1,50 $ par million de tokens (entrée / sortie) |
Tarifs vérifiés le 16 octobre 2026 sur n8n.io/pricing et la grille tarifaire de l’API Gemini. Compte 25 minutes de mise en place.
Construire le workflow pas à pas
Crée un Google Sheet avec un onglet Achats et ces colonnes :
Clé | Date facture | Fournisseur | N° facture | Catégorie | HT | TVA | TTC | Devise | Reçue le | Fichier | Lien email Dans Gmail, crée deux libellés : compta-traitee et compta-a-verifier. Ce sont eux qui garantissent qu’un email n’est jamais traité deux fois.
Ajoute un Gmail Trigger nommé « Nouvelle facture reçue ». Poll Times : toutes les heures. Désactive Simplify : sans ça, les pièces jointes ne sont pas récupérées.
Dans Filters, mets Read Status sur Unread and read emails (une facture déjà ouverte doit aussi être traitée) et cette recherche :
has:attachment filename:pdf (facture OR invoice OR receipt OR reçu) -label:compta-traitee -label:compta-a-verifier Dans Options, active Download Attachments et mets attachment_ comme préfixe. Le premier PDF de l’email sera disponible sous le nom attachment_0.
Juste après le déclencheur, ajoute un nœud Extract from File, opération Extract From PDF, nommé « Lire le PDF ». Input Binary Field : attachment_0. Dans les options, active Join Pages et limite à 5 pages. Dans les Settings, règle On Error sur Continue : un PDF corrompu ne doit pas bloquer les autres.
Mon premier essai plaçait le bloc Paramètres avant la lecture du PDF. Résultat : « Lire le PDF » ne trouvait plus aucun fichier. Le nœud Edit Fields (Set) ne transmet pas les pièces jointes. Lis le PDF en premier, et va chercher les infos de l’email ensuite.
Un nœud Edit Fields (Set) nommé « Paramètres ». Il va chercher les infos de l’email directement dans le déclencheur, et récupère le texte lu dans le PDF :
message_id = {{ $('Nouvelle facture reçue').item.json.id }}
expediteur = {{ $('Nouvelle facture reçue').item.json.from?.value?.[0]?.address ?? "" }}
objet = {{ $('Nouvelle facture reçue').item.json.subject || "" }}
recu_le = {{ DateTime.fromISO($('Nouvelle facture reçue').item.json.date).setZone("Europe/Paris").toISODate() }}
fichier_pdf = {{ $('Nouvelle facture reçue').item.binary?.attachment_0?.fileName ?? "" }}
texte_pdf = {{ ($json.text || "").slice(0, 12000) }}
categories = Logiciels & abonnements, Matériel informatique, Sous-traitance, Déplacements, Formation, Frais bancaires, Autre La liste categories est la seule chose à vraiment personnaliser : reprends les catégories que ton comptable utilise.
Ajoute un nœud Information Extractor nommé « Extraire les données (IA) ». Branche-le en parallèle de la suite, depuis « Paramètres ». Le texte à analyser :
Email de : {{ $json.expediteur }}
Objet : {{ $json.objet }}
Reçu le : {{ $json.recu_le }}
--- Texte du PDF ---
{{ $json.texte_pdf || '(aucun texte lisible dans le PDF)' }} Schema Type : From Attribute Descriptions. Déclare ces 9 attributs, tous requis. Les descriptions sont des consignes pour l’IA, ne les raccourcis pas :
| Attribut | Type | Description |
|---|---|---|
| est_une_facture | Boolean | true uniquement si le texte du PDF est une facture ou un reçu de paiement (pas un devis, pas une relance, pas un bon de commande). false si le texte du PDF est absent. |
| fournisseur | String | Nom commercial du fournisseur (ex : Notion, Canva, OVHcloud) |
| numero_facture | String | Numéro de facture ou de reçu tel qu’imprimé. Chaîne vide si absent. |
| date_facture | String | Date de facture au format AAAA-MM-JJ |
| montant_ht | Number | Montant hors taxes. Si aucune TVA n’apparaît, égal au TTC. |
| tva | Number | Montant de TVA. 0 si absente (fréquent sur les factures SaaS étrangères : autoliquidation). |
| montant_ttc | Number | Montant total payé. 0 si introuvable. |
| devise | String | Code ISO de la devise : EUR, USD, GBP… |
| categorie | String | Une seule catégorie parmi la liste du bloc Paramètres |
Pour categorie, passe la description en expression : Une seule catégorie parmi : {{ $('Paramètres').item.json.categories }}.
Dans Options, remplace le prompt système :
Tu es un assistant comptable rigoureux. Extrais uniquement ce qui est écrit dans le texte du PDF. N'invente jamais un montant ou un numéro : si une valeur est absente, renvoie une chaîne vide ou 0. Les montants sont des nombres avec un point décimal (10.5, pas 10,50 €). Branche le sous-nœud Google Gemini Chat Model (models/gemini-flash-lite-latest, température 0). Règle On Error sur Continue dans les Settings, et un lot de 1 avec 500 ms de délai.
Un nœud Merge nommé « Recoller les infos de l’email », mode Combine › By Position. Entrée 1 : « Paramètres ». Entrée 2 : la sortie de l’IA.
Puis un If nommé « C’est bien une facture ? », avec deux conditions reliées par AND :
{{ $json.output?.est_une_facture ?? false }} is true
{{ $json.output?.montant_ttc ?? 0 }} is greater than 0 La deuxième condition paraît redondante. Elle ne l’est pas : on en reparle dans les pièges.
Sur la branche true, un nœud Google Sheets « Ajouter au registre des achats », opération Append or Update Row, colonne de correspondance Clé. Le mapping :
Clé = {{ ($json.output.fournisseur + "|" + ($json.output.numero_facture || $json.output.date_facture + "|" + $json.output.montant_ttc)).toLowerCase() }}
Date facture = {{ $json.output.date_facture }}
Fournisseur = {{ $json.output.fournisseur }}
N° facture = {{ $json.output.numero_facture }}
Catégorie = {{ $json.output.categorie }}
HT = {{ $json.output.montant_ht }}
TVA = {{ $json.output.tva }}
TTC = {{ $json.output.montant_ttc }}
Devise = {{ $json.output.devise }}
Reçue le = {{ $json.recu_le }}
Fichier = {{ $json.fichier_pdf }}
Lien email = {{ 'https://mail.google.com/mail/u/0/#all/' + $json.message_id }} Dans Options, Cell Format = RAW. Termine la branche par un nœud Gmail « Libellé compta-traitee » (Message › Add Label), avec le Message ID {{ $('Recoller les infos de l’email').item.json.message_id }}.
Sur la branche false du If, un nœud Gmail « Libellé compta-a-verifier » (Message › Add Label), Message ID {{ $json.message_id }}.
C’est ton filet de sécurité. Une fois par semaine, ouvre ce libellé dans Gmail : tu y trouves les devis, les scans et les échecs de l’IA. En général, il y en a peu, et tu sais exactement quoi saisir à la main.
Le test réel : 5 PDF, 3 factures, 2 pièges évités
Pour tester sans toucher à une vraie boîte mail, j’ai généré 5 emails avec de vrais fichiers PDF, et je les ai fait passer dans exactement la même chaîne : lecture du PDF, IA, contrôle, Google Sheets. Seuls les libellés Gmail étaient simulés.
| Ce que c’est | Ce que le workflow a fait | |
|---|---|---|
| Receipt-2384-1193.pdf | Reçu Notion, 10 $, TVA autoliquidée | Ajouté, TVA 0, devise USD |
| Facture-OVH-FR61847203.pdf | Facture française avec TVA 20 % | Ajouté : 11,99 HT / 2,40 TVA / 14,39 TTC |
| Invoice-Canva-INV-04492817.pdf | Facture Canva 110 € | Ajouté |
| Devis-DV-2026-77.pdf | Un devis d’imprimeur | Mis de côté (compta-a-verifier) |
| Scan-facture-F-2026-118.pdf | Une facture scannée (image) | Mis de côté : aucun texte lisible |

Voilà ce que l’IA renvoie pour une vraie facture et pour le devis :

Et le registre, une fois le workflow passé :

Un détail que j’ai aimé : le reçu Notion contient un « Receipt number » et un « Invoice number ». L’IA a retenu le numéro de facture, celui que ton comptable te demandera.
J’ai ensuite rejoué le même lot. La ligne Notion a été mise à jour, pas dupliquée. Et pendant ce second passage, l’IA a renvoyé une erreur 503 sur la facture OVH : le document est parti dans compta-a-verifier, rien n’a été écrit. Exactement ce qu’on veut quand quelque chose casse.
Le coût réel, calculé
Le traçage de n8n mesure 770 tokens en entrée et 100 en sortie par facture. Au tarif payant de Gemini 3.1 Flash-Lite :
770 × 0,25 / 1 000 000 = 0,000193 $
100 × 1,50 / 1 000 000 = 0,000150 $
Total ≈ 0,00034 $ par facture Les 25 factures mensuelles de Camille coûtent moins d’un centime d’IA. Côté durée, il a fallu 53 secondes pour les 5 PDF, dont 47 pour l’IA : le lot de 1 avec délai est volontairement prudent.
Côté n8n, une exécution n’est comptée que lorsque le déclencheur trouve un nouvel email. Avec une facture par jour en moyenne, tu restes autour de 30 exécutions par mois, loin du quota du plan Starter.
Les pièges (appris en les faisant)
Un nœud Edit Fields (Set) ne transmet que les champs que tu déclares, pas les fichiers. Si tu le places avant « Lire le PDF », l’extraction échoue sur un fichier vide. Lis le PDF juste après le déclencheur, puis va chercher les infos de l’email avec $('Nouvelle facture reçue').
Avec la facture scannée, il n’y avait aucun texte à lire. Dans une première version, Flash-Lite a quand même répondu « c’est une facture », en se basant sur l’objet de l’email. Deux corrections : la consigne « false si le texte du PDF est absent », et le contrôle montant_ttc > 0. Une facture sans montant n’a rien à faire dans ton registre.
L’email de l’imprimeur s’intitulait « Votre devis DV-2026-77 (facture à suivre) ». Le filtre Gmail l’a laissé passer, c’est normal. C’est l’IA, en lisant le PDF, qui a reconnu un devis. C’est pour ça que le filtre Gmail reste large et que le vrai contrôle se fait sur le contenu.
En mode par défaut, Sheets interprète ce que tu envoies : un numéro « 000 » devient 0, certaines chaînes deviennent des dates. Mets Cell Format sur RAW dans les options du nœud.
Les conditions du palier gratuit de l’API Gemini autorisent Google à utiliser les contenus envoyés pour améliorer ses produits. Pour tes vraies factures, passe au palier payant, ou branche Claude ou OpenAI à la place.
Avec la facture électronique, de plus en plus de factures arrivent en Factur-X : un PDF qui embarque ses données dans un fichier XML. Pour celles-là, les montants sont déjà dans le fichier, exacts. Dépose une facture dans notre lecteur Factur-X gratuit pour savoir si c’en est une et voir ce qu’elle contient.
Le workflow ne voit que ce qui arrive par email. Les factures à télécharger sur un espace client (énergie, téléphone…) n’y seront pas. Un coup d’œil mensuel au relevé bancaire suffit pour repérer les absents.
Les limites, honnêtement. Seule la première pièce jointe PDF est lue. Les scans ne sont pas traités (il faudrait un OCR, comme Mistral OCR ou Google Document AI, avant l’IA). Les montants en dollars restent en dollars. Et le test portait sur 5 documents : la catégorisation était facile (trois logiciels), elle demandera un œil sur tes cas ambigus les premières semaines.
Adapter à ton activité
Autre métier. Un e-commerçant remplacera les catégories par « Marchandises, Transport, Publicité, Emballages… ». Un formateur ajoutera « Location de salle ». Tout se passe dans le bloc Paramètres.
Autre source, autre destination. Tes factures sont déposées dans un dossier Google Drive ? Remplace le déclencheur par un Google Drive Trigger et télécharge le fichier. Tu préfères Airtable ou Notion à Google Sheets ? Change le nœud d’écriture, en gardant la Clé pour l’upsert. Sur Outlook, utilise le Microsoft Outlook Trigger.
Plus de volume. Au-delà de 100 factures par mois, passe le modèle au palier payant. Si tu reçois beaucoup de scans, ajoute un nœud d’OCR entre « Lire le PDF » et l’IA, uniquement quand texte_pdf est vide.
Make ou n8n pour extraire tes factures ?
J’ai choisi n8n parce qu’il lit le texte d’un PDF nativement (nœud Extract from File) et que l’Information Extractor transforme une liste de champs en sortie structurée, sans écrire de JSON Schema.
| n8n | Make | |
|---|---|---|
| Lire le texte d’un PDF | Natif | Via un service tiers (PDF.co, CloudConvert…) |
| Extraction structurée par l’IA | Information Extractor | Module IA avec structure de sortie |
| Coût de ce workflow | ~30 exécutions/mois | Environ 5 à 6 crédits par facture (estimation) |
| Plan gratuit | Auto-hébergé uniquement | 1 000 crédits/mois, sans carte bancaire |
Avec 25 factures par mois, Make reste dans son plan gratuit côté crédits. Compte en plus le service d’extraction PDF, qui a sa propre tarification. Si tu veux zéro serveur et une interface plus visuelle, c’est une option tout à fait valable.
Côté n8n, la version cloud se teste sans installation sur n8n.io.
Ton registre des achats se remplit maintenant pendant que tu travailles. Le jour où ton comptable le réclame, tu l’envoies. Et tu ne cherches plus que les quelques documents du libellé « à vérifier ».
Quelle est la facture que tu oublies systématiquement de transmettre ?
Pour la suite, le même principe sert à suivre ce que tu vends : regarde comment relancer tes devis automatiquement, ou découvre la version sans serveur avec Make gratuitement.