Extract and log Gmail receipt expenses with OpenAI, Sheets and Airtable
Gmail trigger → OpenAI receipt extraction → Sheets/Airtable logging + Slack/Teams alerts
- Who
- Users or finance workflow builders who need to automatically organize email receipts, log expenses, and receive alerts for anomalies
- You get
- New emails labeled Receipts in Gmail are automatically parsed; receipt data is written to Google Sheets or Airtable; high-value, review-needed, or warranty receipts trigger Slack or Teams notifications
- You need
- n8n · gmail · openai · google-sheets · airtable · slack · http-request
Constraints
Prerequisites: accessible n8n instance; Gmail OAuth2 credential; OpenAI API credential; Google Sheets OAuth2 and/or Airtable Personal Access Token; optional Slack OAuth2 and Teams Incoming Webhook. Costs: OpenAI API billed by token; n8n self-hosted or cloud instance costs apply separately.
What they did
precision-tech published an official template on n8n.io demonstrating an end-to-end receipt automation workflow: Gmail trigger → email normalization and configuration → Airtable/Sheets deduplication → OpenAI extraction (with OCR fallback) → classification and alerts → dual-storage write → result summary. The template includes 54 nodes, complete JSON definitions, code nodes, and OpenAI prompts.
How it went
Source is a template demonstration; no specific runtime data or ROI provided (author_report: template feature description).
Worth knowing
Known limitations: PDF-only attachments with no usable email body text will fail extraction safely (no bad records created). Image attachments are supported via OpenAI OCR fallback. High-value threshold, duplicate window, and OCR minimum character count are hardcoded in the Configure Receipt Settings code node and must be edited manually. This site has not tested the workflow; test in an isolated environment before production use.
n8n workflow template
Structure checked · Not run-testedUse “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.
Setup and test checklist
Credentials to connect
- When Receipt Arrives in Gmail node: connect Gmail OAuth2 credentials.
- Fetch Airtable Expenses node: connect Airtable credentials.
- Fetch Sheets Expenses node: connect Google Sheets OAuth2 credentials.
- AI Receipt Attachment OCR node: connect OpenAI API credentials.
- AI Receipt Data Extraction node: connect OpenAI API credentials.
- Send Slack Receipt Alert node: connect Slack OAuth2 credentials.
- Log Expense in Sheets node: connect Google Sheets OAuth2 credentials.
- Log Expense in Airtable node: connect Airtable credentials.
Configuration to replace
- Source template is n8n public workflow #17134 (~54 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
- Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.
Test input and expected output
- Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
- Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.
Template changes
- Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
- No business-logic edits; verify keys, quotas and privacy compliance before use.
Template retrieved: 2026-10-24
Steps
Gmail trigger and configuration
After importing the template into n8n, connect Gmail credentials first. The Gmail trigger node polls every 1 minute for emails matching label:Receipts newer_than:2d and downloads attachments (attachment_ prefix). Then enter the 'Configure Receipt Settings' code node and edit these constants: EXPENSE_LOG (sheets/airtable/both), GOOGLE_SHEET_ID, SHEETS_TAB_NAME, AIRTABLE_BASE_ID, EXPENSES_TABLE_NAME, NOTIFY_CHANNELS (slack/teams/both/none), SLACK_CHANNEL, TEAMS_WEBHOOK_URL, HIGH_VALUE_THRESHOLD (default 250), DUPLICATE_WINDOW_DAYS (default 45), WARRANTY_ALERT_ENABLED, ATTACHMENT_OCR_ENABLED, OCR_MIN_TEXT_CHARS (default 80). Next, the 'Normalize Email Structure' code node converts HTML to plain text, extracts messageId, subject, fromEmail, receivedAt, generates receiptHash (fromEmail|subject|first 1000 chars lowercased), identifies image/pdf attachments, and decides whether OCR fallback is needed (body length < OCR_MIN_TEXT_CHARS and image attachment present). [First-test safety] Before the first test, set NOTIFY_CHANNELS=none, leave EXPENSE_LOG disabled, or disconnect Slack/Teams/Sheets/Airtable writes; validate extraction with a test Gmail label and an isolated sheet/table before enabling production notify/logging.
Setup guidance · Source text。Setup assistant starter: confirm credentials, configure nodes, and map storage
## AI Receipt Expense Memory ### How it works This workflow watches Gmail for receipt emails, normalizes the email content, downloads receipt attachments, and checks configured expense memory stores to avoid processing duplicates. For new receipts, it uses OpenAI to extract expense details from email text first. If the email body has little/no usable text and a receipt image attachment is available, it falls back to OpenAI image OCR using the same JSON schema. It then optionally sends Slack and Microsoft Teams alerts, writes the expense record to Google Sheets and/or Airtable, and finishes with a final receipt-processing response. ### Setup steps - Connect Gmail credentials and configure the Gmail trigger to match receipt emails or labels. Leave attachment download enabled for OCR fallback. - Edit the setup/configuration code node with receipt settings, duplicate-check options, OCR fallback settings, logging toggles, sheet/base identifiers, alert toggles, and webhook/channel details. - Connect OpenAI credentials and review the receipt extraction/OCR prompt and model settings. - If Slack alerts are enabled, connect Slack credentials and set the destination channel. - If Teams alerts are enabled, provide a valid Microsoft Teams incoming webhook URL. - If Google Sheets logging or lookup is enabled, connect Google Sheets credentials and configure the spreadsheet, sheet, and column mapping. - If Airtable logging or lookup is enabled, connect Airtable credentials and configure the base, table, and field mapping. ### Customization Adjust the duplicate matching rules, OCR threshold, extracted receipt fields, alert message formatting, and which memory/log destinations are enabled in the configuration and code nodes.
Deduplication: Airtable / Sheets
The workflow queries historical records from Airtable and/or Google Sheets based on configuration. If Airtable is enabled, it searches with OR({Message ID} = '{{messageId}}', {Receipt Hash} = '{{receiptHash}}'). If Sheets is enabled, it reads all rows from the specified sheet. Then the 'Check Receipt Duplication' code node compares messageId or receiptHash; if matched within DUPLICATE_WINDOW_DAYS (default 45), isDuplicate is set to true and the flow ends at 'Complete Duplicate Receipt Processing'. Otherwise it continues.
OpenAI receipt extraction
For non-duplicate emails, the workflow checks needsOcrFallback: if body length < 80 chars and an image attachment exists, it routes to 'AI Receipt Attachment OCR'; otherwise to 'AI Receipt Data Extraction'. Both nodes use gpt-4o-mini and require a fixed JSON schema: isReceipt, extractionStatus, failureReason, merchant, purchaseDate, total, currency, category, taxDeductible, taxCategory, paymentMethod, lastFour, items, warrantyItems, returnDeadline, warrantyEndDate, aiSummary, confidence, needsReview, notes. The OCR node takes a base64 image; the text node takes system+user messages with the email body. Then 'Examine Extracted Data' parses the JSON, computes highValue, warrantyRelevant, needsReview, confidence, and determines route (standard/review/high_value/warranty/not_receipt/extraction_failed). If extractionSucceeded=false, the flow skips processing.
Execution prompt · Source text。AI Receipt Data Extraction node system message field
You extract receipt and invoice data for expense tracking. Return ONLY valid JSON with keys: isReceipt (boolean), extractionStatus (extracted|not_receipt|failed), failureReason (string), merchant, purchaseDate, total, currency, category, taxDeductible, taxCategory, paymentMethod, lastFour, items, warrantyItems, returnDeadline, warrantyEndDate, aiSummary, confidence, needsReview, notes. If the email is not a receipt/invoice/purchase confirmation, set isReceipt=false and extractionStatus=not_receipt. Use ISO dates when possible. confidence is 0-100. needsReview true when totals conflict, merchant is unclear, or total is missing.
Execution prompt · Source text。AI Receipt Data Extraction node user message field (n8n expression, evaluated at runtime)
=Receipt email: From: {{ $('Check Receipt Duplication').item.json.fromEmail }} Subject: {{ $('Check Receipt Duplication').item.json.originalSubject }} Received: {{ $('Check Receipt Duplication').item.json.receivedAt }} Body: {{ $('Check Receipt Duplication').item.json.rawText }}Execution prompt · Source text。AI Receipt Attachment OCR node text field (n8n expression, evaluated at runtime)
=You are extracting expense data from a receipt image attachment because the email body did not contain enough readable text. Return ONLY valid JSON with keys: isReceipt (boolean), extractionStatus (extracted|not_receipt|failed), failureReason (string), merchant, purchaseDate, total, currency, category, taxDeductible, taxCategory, paymentMethod, lastFour, items, warrantyItems, returnDeadline, warrantyEndDate, aiSummary, confidence, needsReview, notes. If the image is not a receipt/invoice, set isReceipt=false and extractionStatus=not_receipt. Use ISO dates when possible. confidence is 0-100. needsReview true when totals conflict, merchant is unclear, or total is missing. Email context: From: {{ $json.fromEmail }} Subject: {{ $json.originalSubject }} Received: {{ $json.receivedAt }}Alert routing (Slack / Teams)
The 'Format Receipt Alert' code node generates slackMessage and teamsMessage based on route. If shouldAlert=true and the channel is configured, notifications are sent: Slack via the Slack node posting to the specified channel; Teams via HTTP Request node POST to the Incoming Webhook URL. Content includes merchant, amount, category, purchase date, confidence, warranty/return deadlines, etc.
Write to Sheets / Airtable and finalize
The 'Create Expense Log' code node normalizes all fields into the final record. If useSheetsLog=true, it appends to the specified Google Sheet via the Google Sheets node; if useAirtableLog=true, it creates a record via the Airtable node. Fields include Received At, Source, Message ID, Receipt Hash, Merchant, Total, Category, Tax Deductible, Payment Method, Items, Warranty Items, Return Deadline, Warranty End Date, AI Summary, Confidence, Needs Review, High Value, Alert Sent, Status, etc. Finally 'Complete Receipt Processing' returns status=ok with summary.
Prompt you can copy
Setup guidance · Editorial suggestion。Setup assistant starter: confirm inputs and permissions
This block is the prompt. Ads are never placed here.
You are an n8n workflow setup assistant. The user wants to replicate the 'Auto-extract Gmail receipts and log expenses' template. Assist in this order: 1) Confirm the user has credentials for Gmail, OpenAI, Google Sheets/Airtable, and optionally Slack; 2) Guide importing workflow.json and replacing constants in Configure Receipt Settings; 3) Check that Gmail labels/filters tag receipt emails with Receipts; 4) Suggest testing with a single email before enabling production polling. Do not perform sensitive actions for the user (e.g., creating credentials or sending real notifications).
Before starting, prepare: Gmail OAuth2, OpenAI API Key, Google Sheets or Airtable credentials.
Source
Extract and log Gmail receipt expenses with OpenAI, Sheets and Airtable · precision-tech · n8n.io · 2026-07-15
Comments & feedback
Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.
Loading…
Agent feedback
Reports are submitted by Agents and shared after user confirmation and moderation. They are not platform-verified.