On a schedule
Keep a Google Sheet of every QuickBooks invoice
Your sheet always lists every QuickBooks invoice with its customer, amount, due date and balance, updated every hour.
- Runs
- On a schedule
- Apps
- Google Sheets, QuickBooks
- AI
- Not needed
- Access
- com.intuit.quickbooks.accounting (read); sheet editor
Send this to your assistant
Create a ClickRuntime automation: every hour, copy new and changed QuickBooks invoices into my Invoices sheet with customer, amount, due date and balance, updating rows that already exist.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
An owner wants the sales team to see which customers have paid, but doesn't want to give everyone a QuickBooks login. So someone exports a report each week, pastes it into a sheet, and by Wednesday it's out of date.
An invoice sheet that refreshes every hour gives the whole team a current view of billing and payments, ready for filters, pivot tables and follow-up notes, without anyone touching the books.
What you get out of it
No extra QuickBooks logins
Sales and account managers see invoice status in a sheet, without access to the rest of your accounts.
Always current
Payments recorded in QuickBooks show in the sheet within the hour, so nobody chases a customer who has already paid.
Your own reports
A sheet makes it easy to build the views QuickBooks doesn't offer, like balances by account manager.
No weekly export
The copy-and-paste job disappears, along with the mistakes it brings.
How it works
What happens, step by step
Every hour, ClickRuntime asks QuickBooks for invoices created or changed since the last run.
It reads the invoice IDs already in your sheet.
Changed invoices have their existing row updated; new ones are added at the bottom.
It remembers when it last ran, so each check only looks at recent changes.
Before it runs live
- Connect your Google Sheets account and pick the spreadsheets it may use
- Connect QuickBooks
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Google Sheets and QuickBooks steps into one automation
Under the hood
The code that runs this automation
from datetime import datetime, timezone
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from clickruntime import on_trigger, credentials, http, state, report_fetched
SHEET_ID = "your-spreadsheet-id"
API = "https://quickbooks.api.intuit.com/v3/company/1234567890" # your QuickBooks company id
def qb(method, path, **kw):
r = http.request(method, API + path, params={"minorversion": 73, **kw.pop("params", {})}, **kw, headers={"Accept": "application/json", "Authorization": "Bearer " + credentials.connection("quickbooks", "company")})
return r.raise_for_status() or r.json()
@on_trigger
def run(event):
since = state.get("since") or "2020-01-01T00:00:00Z"
invoices = qb("GET", "/query", params={"query": f"select * from Invoice where MetaData.LastUpdatedTime > '{since}'"})["QueryResponse"].get("Invoice", [])
report_fetched(len(invoices))
if not invoices:
return {"summary": "Nothing new"}
sheets = build("sheets", "v4", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False).spreadsheets()
ids = [r[0] if r else "" for r in sheets.values().get(spreadsheetId=SHEET_ID, range="Invoices!A2:A").execute().get("values", [])]
new = []
for inv in invoices:
row = [inv["Id"], inv.get("DocNumber"), inv["CustomerRef"]["name"], inv["TotalAmt"], inv.get("DueDate"), inv["Balance"]]
if inv["Id"] in ids:
sheets.values().update(spreadsheetId=SHEET_ID, range=f"Invoices!A{ids.index(inv['Id']) + 2}", valueInputOption="RAW", body={"values": [row]}).execute()
else:
new.append(row)
if new:
sheets.values().append(spreadsheetId=SHEET_ID, range="Invoices!A:F", valueInputOption="RAW", body={"values": new}).execute()
state.set("since", max(i["MetaData"]["LastUpdatedTime"] for i in invoices))
return {"updated": len(invoices) - len(new), "added": len(new)}FAQ
Common questions
Does it add a new row when an invoice changes?
Can it include payments or customers too?
What happens to deleted invoices?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Remind customers about overdue invoices and log each chase
Every weekday, customers with overdue QuickBooks invoices get a reminder, each chase is logged in your sheet, and you get a summary email.
See how it worksTurn rows in a billing sheet into QuickBooks invoices
Each new row in your billing sheet becomes a QuickBooks invoice, and the invoice number is written back into the row.
See how it worksAdd expenses from a sheet into QuickBooks
Expenses your team lists in a Google Sheet are added to QuickBooks within the hour and marked as uploaded.
See how it worksKeep exploring
Set up “Keep a Google Sheet of every QuickBooks invoice” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.