AutomationFlowsAI & RAG › Extract Invoice Data From Gmail Pdfs to Google Sheets with Openai and Slack

Extract Invoice Data From Gmail Pdfs to Google Sheets with Openai and Slack

ByAbhishek Gawade @abhi-g on n8n.io

This workflow monitors Gmail for emails with PDF attachments, extracts invoice fields with OpenAI, logs the results to a Google Sheets bookkeeping spreadsheet, and posts high-value invoices to Slack for approval. Triggers every minute when Gmail finds a new email matching the…

Event trigger★★★★☆ complexityAI-powered13 nodesGmail TriggerChain LlmOpenAI ChatOutput Parser StructuredGoogle SheetsSlack
AI & RAG Trigger: Event Nodes: 13 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #16331 — we link there as the canonical source.

This workflow follows the Chainllm → Gmail Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "AI Invoice & Receipt Extractor: email PDF \u2192 structured data \u2192 bookkeeping sheet + approval",
  "tags": [],
  "nodes": [
    {
      "id": "c3d4e5f6-0001-4a10-9a01-cc3333330001",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        40
      ],
      "parameters": {
        "width": 540,
        "height": 760,
        "content": "## \ud83d\udcc4 AI Invoice & Receipt Extractor\n\n**Who it's for:** Small businesses, bookkeepers, finance & ops teams that get invoices and receipts by email and re-type them into a spreadsheet by hand.\n\n**What it does:** When an email with a PDF attachment arrives, it reads the document, an AI extracts the key fields (vendor, invoice number, dates, totals, tax, category), appends a clean row to your bookkeeping sheet, and sends high-value invoices to an approver in Slack.\n\n### How it works\n1. **New Invoice Email** triggers on inbound mail with attachments.\n2. **Extract Text from PDF** reads the attached document.\n3. **Extract Invoice Fields** returns `{ vendor_name, invoice_number, invoice_date, due_date, currency, subtotal, tax_amount, total_amount, category, summary }`.\n4. **Log to Bookkeeping Sheet** appends the row.\n5. **High-Value?** routes invoices over your threshold to **Send for Approval** in Slack.\n\n### Setup (~10 min)\n- Connect **Gmail**, **OpenAI**, **Google Sheets** & **Slack** credentials.\n- In **New Invoice Email**, adjust the search filter (e.g. a label or sender).\n- Set the approval threshold in **High-Value?** and pick your Slack channel.\n- Activate."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0002-4a10-9a01-cc3333330002",
      "name": "Warning",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        820
      ],
      "parameters": {
        "color": 3,
        "width": 540,
        "height": 220,
        "content": "## \u26a0\ufe0f Before you run\n- This template reads the **first PDF attachment** (`attachment_0`). For multi-file emails, add a loop / adjust the binary property.\n- Scanned image-only PDFs need OCR \u2014 swap **Extract Text from PDF** for an OCR / OpenAI vision step.\n- Always keep a human approval step for payments \u2014 the AI extracts, it does **not** pay.\n- Use a cheap model (e.g. `gpt-4o-mini`). This template ships **without credentials** \u2014 connect your own Gmail, OpenAI, Google Sheets & Slack accounts."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0003-4a10-9a01-cc3333330003",
      "name": "Section: Capture",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -680,
        -20
      ],
      "parameters": {
        "color": 4,
        "width": 620,
        "height": 600,
        "content": "## 1 \u00b7 Capture the document\nTrigger on incoming email with an attachment and pull the text out of the PDF.\n**Tune the email filter in \"New Invoice Email\".**"
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0004-4a10-9a01-cc3333330004",
      "name": "Section: Extract",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        -20
      ],
      "parameters": {
        "color": 5,
        "width": 360,
        "height": 600,
        "content": "## 2 \u00b7 Extract fields with AI\nTurn the raw invoice text into clean, structured data: vendor, invoice number, dates, currency, subtotal, tax, total and a spend category."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0005-4a10-9a01-cc3333330005",
      "name": "Section: Record",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        340,
        -20
      ],
      "parameters": {
        "color": 6,
        "width": 540,
        "height": 600,
        "content": "## 3 \u00b7 Record & approve\nAppend a row to your bookkeeping sheet, and send invoices above your threshold to an approver in Slack before they get paid."
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0010-4a10-9a01-cc3333330010",
      "name": "New Invoice Email",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -620,
        240
      ],
      "parameters": {
        "simple": false,
        "filters": {
          "q": "has:attachment"
        },
        "options": {
          "downloadAttachments": true
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c3d4e5f6-0011-4a10-9a01-cc3333330011",
      "name": "Extract Text from PDF",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -340,
        240
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "attachment_0"
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-0012-4a10-9a01-cc3333330012",
      "name": "Extract Invoice Fields",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        0,
        240
      ],
      "parameters": {
        "text": "=Extract the invoice/receipt data from the document text below. If a field is missing, use an empty string (or 0 for numbers). Use ISO dates (YYYY-MM-DD).\n\nDocument text:\n{{ $json.text }}\n\nReturn:\n- vendor_name\n- invoice_number\n- invoice_date\n- due_date\n- currency (ISO code, e.g. USD)\n- subtotal (number)\n- tax_amount (number)\n- total_amount (number)\n- category: best-guess spend category (e.g. Software, Travel, Office, Marketing, Utilities, Other)\n- summary: one short line describing the purchase.",
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.5
    },
    {
      "id": "c3d4e5f6-0013-4a10-9a01-cc3333330013",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -40,
        480
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "c3d4e5f6-0014-4a10-9a01-cc3333330014",
      "name": "Parse Invoice (JSON)",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        140,
        480
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"vendor_name\": \"Acme SaaS Inc.\",\n  \"invoice_number\": \"INV-2026-0042\",\n  \"invoice_date\": \"2026-06-01\",\n  \"due_date\": \"2026-06-15\",\n  \"currency\": \"USD\",\n  \"subtotal\": 200.00,\n  \"tax_amount\": 18.00,\n  \"total_amount\": 218.00,\n  \"category\": \"Software\",\n  \"summary\": \"Monthly subscription \u2013 Pro plan\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "c3d4e5f6-0015-4a10-9a01-cc3333330015",
      "name": "Log to Bookkeeping Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        560,
        120
      ],
      "parameters": {
        "columns": {
          "value": {
            "Tax": "={{ $json.output.tax_amount }}",
            "Total": "={{ $json.output.total_amount }}",
            "Status": "Unpaid",
            "Vendor": "={{ $json.output.vendor_name }}",
            "Category": "={{ $json.output.category }}",
            "Currency": "={{ $json.output.currency }}",
            "Due Date": "={{ $json.output.due_date }}",
            "Received": "={{ $now.toISO() }}",
            "Invoice #": "={{ $json.output.invoice_number }}",
            "Invoice Date": "={{ $json.output.invoice_date }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "gid=0",
          "cachedResultName": "Invoices"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "c3d4e5f6-0016-4a10-9a01-cc3333330016",
      "name": "High-Value?",
      "type": "n8n-nodes-base.if",
      "position": [
        560,
        360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-highvalue",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.output.total_amount }}",
              "rightValue": 1000
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c3d4e5f6-0017-4a10-9a01-cc3333330017",
      "name": "Send for Approval",
      "type": "n8n-nodes-base.slack",
      "position": [
        840,
        360
      ],
      "parameters": {
        "text": "=:heavy_dollar_sign: *Invoice needs approval*\n*{{ $json.output.vendor_name }}* \u2014 {{ $json.output.currency }} {{ $json.output.total_amount }}\nInvoice {{ $json.output.invoice_number }} \u00b7 due {{ $json.output.due_date }} \u00b7 {{ $json.output.category }}\n{{ $json.output.summary }}",
        "select": "channel",
        "resource": "message",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": ""
        },
        "operation": "post",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "High-Value?": {
      "main": [
        [
          {
            "node": "Send for Approval",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "New Invoice Email": {
      "main": [
        [
          {
            "node": "Extract Text from PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Invoice Fields",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Invoice (JSON)": {
      "ai_outputParser": [
        [
          {
            "node": "Extract Invoice Fields",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from PDF": {
      "main": [
        [
          {
            "node": "Extract Invoice Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Invoice Fields": {
      "main": [
        [
          {
            "node": "Log to Bookkeeping Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "High-Value?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow monitors Gmail for emails with PDF attachments, extracts invoice fields with OpenAI, logs the results to a Google Sheets bookkeeping spreadsheet, and posts high-value invoices to Slack for approval. Triggers every minute when Gmail finds a new email matching the…

Source: https://n8n.io/workflows/16331/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This end-to-end AI-powered recruitment automation workflow helps HR and talent acquisition teams automate the complete hiring pipeline—from resume intake and parsing to GPT-4-based evaluation, TA appr

Form Trigger, Output Parser Structured, Google Drive +10
AI & RAG

This workflow automates invoice processing directly from your email inbox.

Gmail Trigger, HTTP Request, Agent +5
AI & RAG

[](https://www.youtube.com/watch?v=MD1krFvVKdU) Automatically extract, evaluate, and shortlist multiple resumes against a selected job description using GPT-4. This smart, scalable n8n workflow helps

Form Trigger, Output Parser Structured, OpenAI Chat +6
AI & RAG

Gmail users report spending significant time manually sorting email, so this tool helps alleviate that burden. Gmail Trigger monitors unread emails every 2 minutes Once an email arrives, the content i

OpenAI Chat, Output Parser Structured, Agent +4
AI & RAG

A smart and reliable resume screening pipeline for modern HR teams. This workflow combines Google Drive (JD & CV storage), OpenAI (GPT-4-based evaluation), Google Sheets (position mapping + result log

Form Trigger, Output Parser Structured, OpenAI Chat +6