Every 15 minutes
Turn emailed supplier invoices into QuickBooks bills
When a supplier emails a PDF invoice, a bill is created in QuickBooks with the PDF attached, and you get an email listing what was added.
- Runs
- Every 15 minutes
- Apps
- Gmail, QuickBooks
- AI
- Yes, uses the built-in AI allowance
- Access
- Gmail modify; QBO accounting
Send this to your assistant
Create a ClickRuntime automation: every 15 minutes, check Gmail for new emails with PDF invoices, read the vendor, number, date and total with AI, create a bill in QuickBooks with the PDF attached, and email me what was created.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
A business with dozens of suppliers gets invoices by email every day. Each one means opening the PDF, finding the vendor in QuickBooks, typing the number, date and total, and saving the attachment. It's dull work, often done in batches days later, which delays payment runs and hides what you owe.
Reading the invoice and creating the bill automatically gets payables into the books the day they arrive, with the original PDF attached for anyone checking later.
What you get out of it
Payables are current
Bills appear in QuickBooks the day the invoice arrives, so cash forecasts include what you actually owe.
The PDF is always attached
Anyone reviewing a bill can open the original invoice from QuickBooks without searching email.
Hours of typing saved
The bookkeeper reviews bills instead of entering them.
Nothing is processed twice
Handled emails are labelled, so a forwarded or re-read message never becomes a second bill.
How it works
What happens, step by step
Every 15 minutes, ClickRuntime checks Gmail for new emails with PDF attachments that match your invoice search.
AI reads each invoice and picks out the vendor, invoice number, date and total.
It finds the vendor in QuickBooks, creates the bill and attaches the PDF.
It labels the email as processed so it's never handled twice.
You get an email listing each bill created.
Before it runs live
- Connect Google through your own Google app (a one-time, 10-minute setup), so it works with your own Gmail
- 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
- Act only on the items that match your own rules, and skip the rest
- Change what the AI looks for, or how it writes the result
- Add another app, for example also send it to Slack
- Combine it with other Gmail and QuickBooks steps into one automation
Under the hood
The code that runs this automation
import base64, json
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from clickruntime import on_trigger, credentials, http, notify, ai, report_fetched
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()
LABEL = "Label_Processed" # id of your "Processed" Gmail label
@on_trigger
def run(event):
gmail = build("gmail", "v1", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False)
msgs = gmail.users().messages().list(userId="me", q="has:attachment filename:pdf label:Invoices -label:Processed").execute().get("messages", [])
report_fetched(len(msgs))
if not msgs:
return {"summary": "Nothing new"}
created = []
for m in msgs:
full = gmail.users().messages().get(userId="me", id=m["id"]).execute()
part = next(p for p in full["payload"].get("parts", []) if p.get("filename", "").lower().endswith(".pdf"))
pdf = base64.urlsafe_b64decode(gmail.users().messages().attachments().get(userId="me", messageId=m["id"], id=part["body"]["attachmentId"]).execute()["data"])
f = ai.generate(f"From this invoice email return JSON with vendor, number, date (YYYY-MM-DD), total:\n{full['snippet']}", max_output_tokens=120,
json_schema={"type": "object", "properties": {"vendor": {"type": "string"}, "number": {"type": "string"}, "date": {"type": "string"}, "total": {"type": "number"}}}).json
vendors = qb("GET", "/query", params={"query": f"select * from Vendor where DisplayName = '{f['vendor']}'"})["QueryResponse"].get("Vendor")
if vendors:
bill = qb("POST", "/bill", json={"VendorRef": {"value": vendors[0]["Id"]}, "DocNumber": f["number"], "TxnDate": f["date"], "Line": [{"Amount": f["total"],
"DetailType": "AccountBasedExpenseLineDetail", "AccountBasedExpenseLineDetail": {"AccountRef": {"value": "7"}}}]})["Bill"]
meta = {"AttachableRef": [{"EntityRef": {"type": "Bill", "value": bill["Id"]}}], "FileName": part["filename"], "ContentType": "application/pdf"}
qb("POST", "/upload", files={"file_metadata_0": (None, json.dumps(meta), "application/json"), "file_content_0": (part["filename"], pdf, "application/pdf")})
created.append(f"{f['vendor']} #{f['number']}: ${f['total']:,.2f}" + ("" if vendors else " (vendor not found, skipped)"))
gmail.users().messages().modify(userId="me", id=m["id"], body={"addLabelIds": [LABEL]}).execute()
notify.email_me(f"{len(created)} supplier invoices processed", "\n".join(created))
return {"processed": len(created)}FAQ
Common questions
Which emails are treated as invoices?
What if the vendor isn't in QuickBooks?
Can I approve bills before they're created?
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
Create QuickBooks invoices from emails you label
Label an email thread Invoice Needed and a QuickBooks invoice for the client and items it mentions is created and sent.
See how it worksSend polite Gmail reminders for overdue QuickBooks invoices
Every weekday, customers with overdue QuickBooks invoices get a reminder from your Gmail address, firmer as the invoice ages, and you get a summary.
See how it worksLabel new emails automatically
New mail is sorted into labels like Inquiry, Invoice and Newsletter within minutes of arriving.
See how it worksKeep exploring
Set up “Turn emailed supplier invoices into QuickBooks bills” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.