Google Sheets + Gmail: inventory approvals, fewer stockouts
Inventory looks “fine” right up until it isn’t. A receipt gets logged late, someone pulls materials without telling anyone, and now production is stuck because the spreadsheet was quietly wrong. This inventory approvals automation fixes that gap.
Operations Managers feel the pain when the floor is waiting on materials. A Marketing lead running a small product line sees it as delayed launches. And business owners just see the same problem in a different language: avoidable surprises.
This n8n workflow turns receipts and issue requests into clean, synced records (Google Sheets + Supabase), then handles approvals and low-stock emails in Gmail. You’ll see what it automates, what results you can expect, and what you need to run it.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Sheets + Gmail: inventory approvals, fewer stockouts
flowchart LR
subgraph sg0["Flow 1"]
direction LR
n16@{ icon: "mdi:database", form: "rounded", label: "Append Raw Materials", pos: "b", h: 48 }
n17["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Calculate Total Price"]
n18["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Calculate Updated Current St.."]
n19["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Validate Quantity Received"]
n20@{ icon: "mdi:database", form: "rounded", label: "Initialize New Product stock", pos: "b", h: 48 }
n21@{ icon: "mdi:database", form: "rounded", label: "Update Current Stock", pos: "b", h: 48 }
n22@{ icon: "mdi:database", form: "rounded", label: "LookUp Current stock", pos: "b", h: 48 }
n23["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>New Row Current Stock"]
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Current Stock Update"]
n25["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Search Current Stock"]
n26["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/itemLists.svg' width='40' height='40' /></div><br/>Format response"]
n27["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge"]
n28["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Low stock Detection2"]
n29["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Receive Raw Materials Webhook"]
n30@{ icon: "mdi:swap-vertical", form: "rounded", label: "Standardize Raw Material Data", pos: "b", h: 48 }
n31@{ icon: "mdi:database", form: "rounded", label: "Lookup Existing Stock", pos: "b", h: 48 }
n32@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check If Product ID Exists", pos: "b", h: 48 }
n33["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>New Record Row"]
n34@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Trigger Low Stock Alert", pos: "b", h: 48 }
n35@{ icon: "mdi:message-outline", form: "rounded", label: "Send Low Stock Email Alert", pos: "b", h: 48 }
n27 --> n32
n33 --> n25
n26 --> n20
n26 --> n23
n16 --> n19
n22 --> n28
n28 --> n34
n25 --> n27
n21 --> n22
n17 --> n16
n17 --> n33
n31 --> n27
n34 --> n35
n32 --> n18
n32 --> n26
n19 --> n31
n29 --> n30
n30 --> n17
n18 --> n21
n18 --> n24
end
subgraph sg1["Flow 2"]
direction LR
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Get Approvals"]
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Update Stock"]
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Searck Issues"]
n10["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Update Current Stck"]
n12@{ icon: "mdi:database", form: "rounded", label: "Update Current Stock1", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "LookUp Current stock1", pos: "b", h: 48 }
n14["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Low stock Detection1"]
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge1"]
n36@{ icon: "mdi:message-outline", form: "rounded", label: "Low Stock Email Alert", pos: "b", h: 48 }
n40@{ icon: "mdi:swap-vertical", form: "rounded", label: "Format Approval Response", pos: "b", h: 48 }
n41["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Verify Approval Data"]
n42@{ icon: "mdi:database", form: "rounded", label: "Retrieve Issue Request Details", pos: "b", h: 48 }
n43@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Process Approval Decision", pos: "b", h: 48 }
n44@{ icon: "mdi:database", form: "rounded", label: "Get Stock for Issue Update f..", pos: "b", h: 48 }
n45@{ icon: "mdi:database", form: "rounded", label: "Update Stock After Issue", pos: "b", h: 48 }
n46["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Materials Issue Table Update"]
n47@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Is Stock is Low", pos: "b", h: 48 }
n15 --> n43
n3 --> n12
n3 --> n10
n1 --> n40
n9 --> n15
n47 --> n36
n14 --> n47
n41 --> n42
n41 --> n9
n13 --> n14
n12 --> n13
n40 --> n41
n43 --> n45
n43 --> n46
n43 --> n44
n42 --> n15
n44 --> n3
end
subgraph sg2["Flow 3"]
direction LR
n0@{ icon: "mdi:database", form: "rounded", label: "Append Material Request", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-vertical", form: "rounded", label: "Standardize Data", pos: "b", h: 48 }
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Receive Issue Request"]
n5@{ icon: "mdi:message-outline", form: "rounded", label: "Send Approval Request", pos: "b", h: 48 }
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Prepare Approval"]
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Create Record Issue"]
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/supabase.svg' width='40' height='40' /></div><br/>Search Product ID"]
n11["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge Lookups"]
n37["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Validate Issue Request Data"]
n38["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Verify Requested Quantity"]
n39@{ icon: "mdi:database", form: "rounded", label: "Check Available Stock for Is..", pos: "b", h: 48 }
n11 --> n6
n6 --> n5
n2 --> n37
n8 --> n11
n7 --> n8
n4 --> n2
n0 --> n39
n38 --> n0
n38 --> n7
n37 --> n38
n39 --> n11
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n32,n34,n43,n47 decision
class n16,n20,n21,n22,n31,n12,n13,n42,n44,n45,n0,n39 database
class n29,n1,n4 api
class n17,n18,n19,n28,n3,n14,n41,n6,n37,n38 code
classDef customIcon fill:none,stroke:none
class n17,n18,n19,n23,n24,n25,n26,n27,n28,n29,n33,n1,n3,n9,n10,n14,n15,n41,n46,n4,n6,n7,n8,n11,n37,n38 customIcon
The Problem: Inventory data drifts, then breaks
Manual inventory tracking usually fails in boring ways. A raw-material receipt comes in, someone means to update the sheet “after lunch,” and it slips. Issue requests get handled in Slack, on paper, or by a quick tap on the shoulder, which never makes it into your records. Then you’re stuck reconciling two truths: what the spreadsheet says and what the shelf actually has. The cost isn’t only stockouts. It’s the mental load of second-guessing every number, plus the time spent chasing approvals, digging up who approved what, and explaining why you ran out again.
The friction compounds. These are the usual failure points that keep showing up.
- Receipts get recorded late, so your “current stock” is always behind reality by a day.
- Issue requests are approved in scattered places, which means there’s no clean audit trail when questions come up.
- Low-stock checks happen when someone remembers, and honestly, nobody remembers during busy weeks.
- Duplicated or inconsistent product IDs create silent errors that only surface during production.
The Solution: Real-time inventory updates with email approvals
This workflow creates one reliable path for raw materials to enter and leave inventory. When a receipt is submitted (typically from a form), n8n normalizes the fields, calculates totals, and records the event in Google Sheets while also writing to Supabase for redundancy and reporting. When a material issue request comes in, the workflow validates the request, checks available stock, then sends an approval email through Gmail with an approve/reject link. Once the approver responds, n8n captures that decision, updates the request status, deducts stock if approved, and re-checks thresholds. If inventory drops under your minimum level (default is 50), Gmail alerts go out immediately, so you find out before the stockout hits.
The workflow starts with two inputs: receipts and issue requests (both via webhooks). In the middle, it cleans the data, checks product existence, updates Sheets and Supabase, then routes approvals and stock alerts through Gmail. The output is simple: your records stay consistent, approvals are logged, and low stock triggers an email without anyone babysitting the spreadsheet.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you log about 10 receipts a week and handle 15 issue requests. Manually, if each one takes roughly 10 minutes to update the sheet, check stock, and message someone for approval, that’s around 4 hours weekly. With this workflow, submitting the form takes about a minute, then n8n updates Sheets and Supabase in the background while Gmail handles the approval click. You still review exceptions, but the routine work mostly disappears.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets for your receipt and issue logs
- Gmail to send approvals and low-stock alerts
- Supabase API key and URL (get it from your Supabase project settings)
Skill level: Intermediate. You’ll connect credentials, map a few fields, and paste webhook URLs into your form tool.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A receipt or issue request hits a webhook. Your form submission (for raw materials received or materials requested) triggers the workflow immediately, so updates don’t wait for someone to “do admin later.”
The workflow cleans and validates the data. n8n standardizes product IDs and quantities, calculates totals for receipts, and rejects bad inputs before they pollute your inventory history.
Stock is updated in two places. Google Sheets is updated for day-to-day visibility, and Supabase is updated for consistency and easier downstream reporting. Existing products get their stock incremented; new products get inserted as new rows/records.
Approvals and low-stock alerts go through Gmail. For issue requests, the approver receives an email with an approval link, and the callback updates both the request status and stock if approved. After any change, low stock is checked and alerts are emailed if you’ve dropped below the threshold.
You can easily modify the low-stock threshold to match your reorder policy based on lead time and minimum order quantities. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Webhook Trigger
This workflow starts from three webhook endpoints to capture raw materials intake, issue requests, and approval callbacks.
- Open Raw Materials Webhook and set Path to
Pb-raw-materialswith HTTP MethodPOST. - Open Issue Request Webhook and set Path to
raw-materials-issuewith HTTP MethodPOST. - Open Receive Approval Callback and set Path to
/approve-issue. - Ensure the approval email link in Normalize Issue Payload matches your n8n domain: Approval Link uses
https://your-n8n-domain/webhook/approve-issue?submissionId={{ $json.body['Submission ID'] }}.
Step 2: Connect Google Sheets
Google Sheets drives the inventory database, issue logs, and raw materials intake records across multiple nodes.
- In Add Material Request Row, select the document
Plumbee Raw Material Delivery (Responses)and sheetMaterials Issued, with Operation set toappend. - In Append Raw Materials Row, select the document
Plumbee Raw Material Delivery (Responses)and sheetRaw Materials, with Operation set toappend. - In Update Stock Sheet and Update Stock Sheet Main, keep Operation as
updateand ensure Matching Columns includesProduct ID. - Ensure all stock lookup nodes—Check Stock for Issue, Fetch Existing Stock, Lookup Stock Sheet, Lookup Stock Sheet Main, and Fetch Stock for Issue Update—filter by Product ID using
{{ $json["Product ID"] }}. - Credential Required: Connect your Google Sheets credentials to all Google Sheets nodes (12+ nodes handle stock, raw materials, and issue logs).
Product ID, Current Stock, Minimum Stock Level) to avoid mapping errors across updates and lookups.Step 3: Connect Supabase
Supabase stores the canonical inventory and issue records alongside Google Sheets.
- In Insert Raw Material Record, set Table to
Raw Materialsand Data to Send toautoMapInputData. - In Insert Issue Record and Update Issue Table, set Table to
Materials Issuedand keep Operation asupdatefor status updates. - In Lookup Product Record, Query Stock Records, Update Stock Record, Insert Stock Row, and Supabase Stock Update, set Table to
Current Stockwith filters based on{{ $json["Product ID"] }}. - Credential Required: Connect your Supabase credentials to all Supabase nodes (9 nodes handle issue records and stock tables).
Step 4: Set Up Data Normalization and Validation
Incoming webhook data is normalized and validated before it is stored or used in calculations.
- In Normalize Raw Material Data, map payload fields using expressions like
{{ $json.body.product_id }},{{ $json.body.quantity_received }}, and{{ $json.body.material_name }}. - In Normalize Issue Payload, set Approval Link to
https://your-n8n-domain/webhook/approve-issue?submissionId={{ $json.body['Submission ID'] }}and Status toPending. - Confirm Validate Received Qty and Validate Issue Request are enabled to throw errors on invalid quantities.
- Review Compute Total Cost to ensure it parses
Quantity ReceivedandUnit Pricecorrectly for total calculation.
product_id vs Product ID), the normalization steps will output blank fields.Step 5: Set Up Approval Routing and Email
The issue request flow enriches the request, sends approval, and processes decision callbacks.
- Ensure Verify Requested Amount follows Validate Issue Request and outputs to both Add Material Request Row and Insert Issue Record in parallel.
- Confirm Combine Lookup Streams aggregates Check Stock for Issue and Lookup Product Record before Prepare Approval Data.
- In Prepare Approval Data, keep the logic that sets Is Enough and Current Stock based on stock lookup and request quantity.
- In Email Approval Request, update Send To from
[YOUR_EMAIL]and keep the subject expressionApproval Required: Material Issue Request - {{ $json['Product ID'] }}. - Credential Required: Connect your Gmail credentials to Email Approval Request.
Receive Approval Callback flows to Format Approval Callback then Validate Approval Details, which outputs to both Fetch Issue Request Details and Find Issue Entries in parallel before Merge Issue Lookups and Branch on Approval Decision.
Step 6: Configure Stock Updates and Low Stock Alerts
This stage updates inventory across Sheets and Supabase, and sends low stock warnings through Gmail.
- When approvals are approved, Fetch Stock for Issue Update flows into Compute Stock Deduction, which outputs to both Update Stock Sheet and Update Stock Record in parallel.
- For new raw material intake, Compute Total Cost outputs to both Append Raw Materials Row and Insert Raw Material Record in parallel.
- When a product is found, Compute New Stock Level outputs to both Update Stock Sheet Main and Supabase Stock Update in parallel.
- For new products, Deduplicate Response outputs to both Add New Stock Item and Insert Stock Row in parallel.
- Ensure both low stock detectors are wired: Lookup Stock Sheet → Detect Low Stock A → Check Low Stock Flag → Dispatch Low Stock Email 2, and Lookup Stock Sheet Main → Detect Low Stock B → Route Low Stock Alert → Dispatch Low Stock Email.
- Credential Required: Connect your Gmail credentials to Dispatch Low Stock Email and Dispatch Low Stock Email 2.
50).Step 7: Test and Activate Your Workflow
Run end-to-end tests for each webhook path and verify updates across Sheets, Supabase, and email notifications.
- Use the Execute Workflow button and send a sample payload to Raw Materials Webhook to confirm Compute Total Cost outputs and records are appended/inserted.
- Send a test request to Issue Request Webhook and verify Email Approval Request sends an email with approval/reject links.
- Click an approval link to trigger Receive Approval Callback and confirm Update Issue Status Sheet, Update Issue Table, and stock updates execute correctly.
- Check that low stock emails send when Is Low is true in both alert paths.
- Once validated, switch the workflow to Active for production use.
Common Gotchas
- Google Sheets credentials can expire or lack the right spreadsheet permissions. If things break, check the n8n Credentials page and the sheet sharing settings first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Gmail approvals can fail if the approver is signed into a different Google account than the one expected, or if the Gmail scope is too limited. Reconnect the Gmail credential and send a test approval email before going live.
Frequently Asked Questions
About an hour if your Sheets, Supabase, and Gmail credentials are ready.
No. You will mostly connect accounts and map form fields to the right columns.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Supabase and Gmail usage (usually minimal for small teams).
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and it’s one of the best tweaks to make. You can change the minimum stock threshold inside the low-stock detection logic (the Detect Low Stock code nodes and the If routing that triggers Gmail). Common customizations include different thresholds per product, separate alerts for “reorder now” vs. “watch,” and sending alerts to a shared inbox instead of one person.
Usually it’s permissions or an expired OAuth connection. Reconnect the Google Sheets credential in n8n, then confirm the spreadsheet is shared with the same Google account used by the credential. Also double-check the Sheet ID and tab names because a renamed tab will break lookups. If it fails only under load, you may be hitting Google API limits, so slow down batches or reduce parallel runs.
If you self-host, there’s no execution cap (it mostly depends on your server and Google API limits).
Often, yes, because approvals, branching, and “write to two systems then reconcile” logic gets expensive and awkward in simpler tools. n8n handles multi-branch flows (like approved vs. rejected) cleanly, and the webhook-to-webhook approval callback pattern is a natural fit. You also get the option to self-host, which matters once you’re processing lots of requests. Zapier or Make can still be fine for a lightweight version, but you’ll likely end up compromising on the audit trail or paying more as volume grows. Talk to an automation expert if you want a quick recommendation based on your volumes.
Once receipts, issues, approvals, and alerts run through one system, inventory stops being a weekly guessing game. Set it up, trust the numbers, and get back to work that actually moves the business.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.