We use cookies to understand how you use our site and improve your experience. Privacy Policy

Back to Blog
Automation Workflows

QuickBooks Invoice Sync to Sheets with n8n

n8n
n8n Resources Team
June 15, 2026

Ready to automate?

Browse 5,000+ copy-paste n8n workflow templates.

Finance teams export invoices from QuickBooks, paste rows into spreadsheets, and chase overdue payments by hand. The data exists in QuickBooks, but it's siloed. Nobody sees the live receivables picture without pulling a manual report — and by the time someone pulls it, it's already stale.

The fix is a single n8n workflow: listen for new QuickBooks invoices via webhook, write each one to a shared Google Sheets register, and fire a Slack alert when a payment goes overdue. Once it's running, your accounts receivable data updates itself, and your team stops maintaining a spreadsheet nobody trusts.

What You'll Build

A three-part automation:

  1. Real-time trigger: QuickBooks sends a webhook the moment an invoice is created or updated.
  2. Spreadsheet sync: n8n maps the invoice fields — number, client name, amount, due date, status — and appends a row to Google Sheets.
  3. Overdue alert: An IF node checks the due date. If an invoice is past due and still unpaid, n8n posts a message to Slack.

The result is a live invoice register that keeps itself current and surfaces overdue items without anyone monitoring the queue.

Prerequisites

  • An n8n instance (cloud or self-hosted)
  • A QuickBooks Online account with a connected Developer App (needed for OAuth2 credentials and webhook access)
  • A Google Sheets spreadsheet set up as your invoice register
  • A Slack workspace and channel for alerts (optional but recommended)

Set Up Your Google Sheet

Before building the workflow, create a Google Sheet with these column headers in row 1:

Invoice Number | Client | Amount | Issue Date | Due Date | Status | QB Invoice ID

The QB Invoice ID column is your deduplication key — it prevents duplicate rows when QuickBooks fires multiple events for the same invoice.

The n8n Workflow: Step by Step

Step 1: Webhook Trigger Node

Add a Webhook Trigger node. Set the HTTP method to POST and note the generated webhook URL. In the QuickBooks Developer portal, create a webhook subscription pointed at that URL, subscribing to the Invoice.Create and Invoice.Update event types.

QuickBooks signs its webhook payloads with a verifier token. Copy that token into the Webhook node's Header Auth field so n8n validates every incoming request before processing it.

Step 2: QuickBooks Node — Get Invoice

The QuickBooks webhook payload contains only a change notification, not the full invoice data. Add a QuickBooks node configured with your OAuth2 credentials. Select the Get Invoice operation and pass in the invoice ID from the webhook body:

{{ $json.body.eventNotifications[0].dataChangeEvent.entities[0].id }}

This returns the complete invoice record: customer name, line items, total amount, due date, and payment status.

Step 3: Set Node — Map Fields

Add a Set node to extract only the fields you need and give them clean names for the sheet:

  • invoice_number{{ $json.DocNumber }}
  • client{{ $json.CustomerRef.name }}
  • amount{{ $json.TotalAmt }}
  • issue_date{{ $json.TxnDate }}
  • due_date{{ $json.DueDate }}
  • status{{ $json.Balance > 0 ? 'Unpaid' : 'Paid' }}
  • qb_invoice_id{{ $json.Id }}

The expression for status checks the remaining balance rather than a status string — QuickBooks balance of 0 means fully paid regardless of the EmailStatus field value.

Step 4: Google Sheets Node — Append Row

Add a Google Sheets node with your OAuth2 credentials. Select the Append Row operation, point it at your invoice register spreadsheet, and map each column header to the corresponding field from the Set node.

Turn on the deduplication setting and set QB Invoice ID as the match key. When n8n receives an update event for an invoice that already has a row, it updates that row instead of adding a duplicate.

Step 5: IF Node — Check for Overdue Status

Add an IF node after the Google Sheets step. Configure two conditions joined by AND:

  • {{ new Date($json.due_date) < new Date() }} evaluates to true (due date is in the past)
  • {{ $json.status }} equals Unpaid

If both conditions are true, the invoice is overdue and still unpaid.

Step 6: Slack Node — Send Overdue Alert

On the true branch, add a Slack node. Set the channel to your #finance-alerts channel and the message to something like:

Overdue invoice: #{{ $json.invoice_number }} — {{ $json.client }} owes ${{ $json.amount }}, due {{ $json.due_date }}.

On the false branch, add a No Operation node. The workflow exits silently for current invoices.

Full Workflow at a Glance

  1. Webhook Trigger — receives Invoice.Create or Invoice.Update from QuickBooks
  2. QuickBooks node — fetches complete invoice record by ID
  3. Set node — maps QuickBooks fields to flat column names
  4. Google Sheets node — appends or updates the invoice row (deduplicates on QB Invoice ID)
  5. IF node — checks if due date has passed and status is Unpaid
  6. Slack node (true branch) — posts overdue alert to finance channel
  7. No Operation node (false branch) — silent exit for current invoices

Handling Payment Updates

When a client pays, QuickBooks fires an Invoice.Update event. The workflow catches it, re-fetches the invoice (now with Balance = 0), sets status to Paid in the Set node, and updates the Google Sheets row in place. Your register reflects the payment without any manual update.

If you prefer a polling approach — for teams that don't need real-time sync — replace the Webhook Trigger with a Schedule Trigger running nightly. Add a QuickBooks node set to Get Many Invoices with a filter for invoices updated in the last 24 hours, and connect it to the same Set → Sheets → IF chain. The logic is identical; only the trigger differs.

What This Replaces

Manual QuickBooks exports typically happen once a week or less. In that window, invoices go unpaid for days before anyone notices. Payment reminders go out late. Cash flow forecasting is based on week-old numbers.

With this workflow running, the Google Sheets register is always current. A finance team member can open the sheet at any time and see real AR state. Pivot tables on payment trends build themselves off live data. Overdue alerts reach the right channel within seconds of a due date passing midnight.

The setup takes under an hour. Ongoing maintenance is zero.

What to Build Next

With invoice data flowing into Sheets, a natural extension is a weekly AR aging report: a Schedule Trigger groups unpaid invoices by days-outstanding bucket (0–30, 31–60, 60+) and posts the summary to Slack or sends it as an email attachment via Gmail.

You can also extend the overdue branch to create a follow-up task in Asana or Notion when an invoice crosses 30 days past due — turning the alert into an automated collections queue.

For pre-built QuickBooks and Google Sheets workflow templates, browse the n8n template library. If you're building out a broader finance automation stack, see how teams structure end-to-end accounting workflow automation with n8n.

Enjoyed this article?

Share it with others who might find it useful