30-second verdict
The native HubSpot and QuickBooks Online integration is free to connect and good at two things: creating an invoice from a deal by hand, and showing invoice status inside HubSpot. It will not create an invoice automatically when a deal hits Closed Won. For that you need Zapier or Make, two guard properties on the deal, and a second automation that writes payments back. The full build below takes a focused day if your line items are clean. If you send fewer than about 10 invoices a month, skip the automation entirely and use the native create-invoice button. If we build it for you, plan on 8 to 15 hours at our flat $150 per hour.
Closed-won is supposed to mean invoiced. In most small companies it means invoiced once someone remembers, and the gap is measured in days. If you send 40 invoices a month and each one waits two days for a human to key it in, you are floating customers a free week of cash every month, plus whatever the typos cost you.
This guide is the invoicing slice of a quote-to-cash system we built for a client: deal-stage-triggered QuickBooks invoicing with payment reconciliation, inside a HubSpot setup that also tracked 300+ permits across connected pipelines. The version below is the same skeleton, trimmed to what most teams need. It is core RevOps work for us, and most of it you can do yourself.
Prerequisites, honestly
- QuickBooks Online, any tier. QuickBooks Desktop and QuickBooks Self-Employed do not work with anything in this guide. Multicurrency needs Essentials or higher.
- HubSpot free CRM is enough. You do not need Sales Hub Professional, because Zapier or Make watches the deal stage, not a HubSpot workflow. You do need admin rights to create deal properties.
- A paid Zapier plan if you go the Zapier route. QuickBooks Online is a premium app there, and this is a multi-step build. On Make there is no premium gate for QuickBooks.
- Your bookkeeper's sign-off on tax codes and invoice numbering before you automate anything. Five minutes now saves a bad month at filing time.
What the native integration does, and where it stops
HubSpot's own QuickBooks Online app is free to connect from the App Marketplace, and you should connect it no matter what else you build. As of mid-2026 it handles two-way contact sync, product sync, and pulls invoices from QuickBooks into HubSpot as read-only records, so a rep can see invoice status without messaging accounting. What it will not do is create an invoice because a deal changed stage. Invoice creation is a button a human clicks on the deal record. Check the integration settings page when you connect, because this list changes.
| Job | Native integration | Zapier or Make |
|---|---|---|
| Create invoice on Closed Won | No. Manual button on the deal | Yes, automatic on stage change |
| See invoice status in HubSpot | Yes, as synced read-only invoice records | Yes, as deal properties you can filter and report on |
| Map deal line items to invoice lines | Only what a person picks by hand | Full control, including tax codes per line |
| Mark the deal Paid or Partially paid | No deal property for it | Yes, via the reconciliation automation |
| Contact and product sync | Yes, leave this job here | Possible, but do not rebuild it |
The pattern that works is both at once: the native app for sync and visibility, Zapier or Make for the trigger and the write-back. They run side by side without fighting, because the custom properties you create below belong to you, not to either integration.
Step 1: Decide what "invoice this" actually means
Do this before opening any tool. Closed Won is the obvious trigger, and for plenty of businesses it is the wrong one. If you take a 50% deposit at contract signing, the first invoice should go out before the deal is technically won. If billing starts at kickoff, Closed Won fires too early by weeks.
The rule we use: trigger on a stage if invoicing happens at the same moment for every deal. Trigger on a checkbox a human ticks (we name the property Ready to invoice) if a judgment call is involved. Do not automate judgment. Automate the typing that follows it.
One pipeline first. Get it boring and trusted on your main pipeline, then clone it for the others. Every quote-to-cash build we have seen fail tried to cover three pipelines with different rules on day one.
Step 2: Prepare QuickBooks Online
- Products and services. In QuickBooks, open the gear menu, then Products and services. Every line you ever bill must exist here, with the exact name you will map from HubSpot. The API rejects invoice lines that point at items that do not exist, and the automation dies quietly.
- Tax codes. In Canadian QuickBooks, every invoice line needs a sales tax code, like HST ON. Leave it blank and QuickBooks throws "Business Validation Error: Make sure all your transactions have a sales tax rate before saving" and the invoice never lands. Ask your bookkeeper which code applies per product, and write it down.
- Numbering. Gear menu, Account and settings, Sales: leave Custom transaction numbers off so QuickBooks auto-numbers invoices. Your automation reads the number back. It should never write one.
- Customers. Do not pre-create them. The automation will find or create customers by email, which avoids the name-matching mess covered below.
Step 3: Create four deal properties in HubSpot
In HubSpot, go to Settings > Properties, select Deal properties, and create:
- QuickBooks invoice number, single-line text. Human-facing, shows on the deal.
- QuickBooks invoice ID, single-line text. QuickBooks' internal ID. The reconciliation step matches on this, not on the number.
- Invoice status, dropdown select with exactly four options: Not invoiced, Invoice created, Partially paid, Paid.
- Amount paid, number, formatted as currency.
Resist the urge to make a Paid checkbox instead. Partial payments are why the status field has four values, and a checkbox forces somebody to lie when half the money arrives. Add all four properties to the deal record sidebar so reps see them without clicking.
Step 4: Build the create-invoice automation
In Zapier, five steps:
- Trigger: HubSpot, New Deal in Stage. Pick your pipeline and the stage you chose in step 1.
- Filter: only continue if QuickBooks Invoice Number "Does not exist". This is your duplicate guard. Never skip it.
- QuickBooks Online, Find Customer: search by the contact's email, and tick Create QuickBooks Online Customer if it doesn't exist yet.
- QuickBooks Online, Create Invoice: customer from the previous step, then the line items: product/service mapped to the exact item name from step 2, quantity, rate, and a tax code on every line.
- HubSpot, Update Deal: write the returned invoice number into QuickBooks invoice number, the internal ID into QuickBooks invoice ID, and set Invoice status to Invoice created.
Now the honest part about line items. Zapier's deal trigger does not hand you the deal's line items. To get them, you bolt on the HubSpot API Request action to pull the deal's line item associations, then loop over the results, and the build stops feeling like Zapier and starts feeling like programming. If your deals routinely carry more than one line item, build this in Make instead: Get a Deal, an Iterator over the line items, an Array Aggregator into the invoice's line array. Same logic, far fewer workarounds. We compared the tools properly in Zapier vs Make vs n8n. If every deal is one line, like a fixed-fee service, stay in Zapier and map the deal's Amount to a single line.
Where this breaks: duplicate invoices
A rep drags a deal to Closed Won. The founder drags it back during pipeline review. Sales drags it forward again on Friday. The trigger fires twice. The filter on QuickBooks invoice number catches almost all of this, but there is a small race: if the second trigger fires before the first run writes the number back, you get two invoices. We have watched it happen on bulk imports, where 50 deals hit the stage inside a minute. Catch it with a monthly check: count deals where QuickBooks invoice number is known, count invoices in QuickBooks for the same period, and investigate any gap. And if you ever bulk-import closed deals, turn the automation off first and invoice those by hand.
Where this breaks: the customer name collision
QuickBooks requires display names to be unique across customers, vendors, and employees combined. The first time you invoice a company you also buy from, the automation dies with "The name supplied already exists" and nothing tells the rep. Design around it: match customers by email, never by company name, and after the first invoice store the QuickBooks customer ID on the HubSpot company record (a single-line text property named QuickBooks customer ID) so later invoices skip name matching entirely. When the error does fire, the fix inside QuickBooks is to rename the vendor, for example "Acme Inc (vendor)".
Step 5: The reconciliation loop back into HubSpot
Invoicing without reconciliation is half a system. The deal says won, finance says unpaid, and the founder asks both teams in the same meeting. The loop is a second automation:
- Trigger: QuickBooks Online, New Payment. Fires when a payment is recorded, including ones your bookkeeper applies by hand.
- QuickBooks Online, Find Invoice: look up the invoice from the payment's linked transaction. You need this step because the payment does not tell you the remaining balance. The invoice does.
- HubSpot, Find Deal: search on the QuickBooks invoice ID property using the ID from the previous step. This is why you stored it in step 4.
- Paths on the invoice's Balance: if Balance equals 0, update the deal to Invoice status Paid and Amount paid equal to the invoice total. If Balance is greater than 0, update to Partially paid and Amount paid equal to total minus balance.
One thing this loop quietly depends on: payments must actually be applied to invoices in QuickBooks. A deposit sitting in the bank feed, matched to nothing, fires no trigger. If your bookkeeper batches reconciliation to month-end, your deal statuses will run up to a month stale. That is a process conversation, not a setting.
What the loop buys you: a saved deal view filtered to Invoice status is any of Invoice created, Partially paid with a close date more than 30 days back. That view is your receivables chase list, inside the CRM, next to the contact's phone number. Nobody exports a CSV to find out who owes what.
Step 6: Handle partial payments properly
Partial payments are normal, not an edge case. A 50% deposit. A customer short-paying a disputed line. A grant covering part of a program fee. QuickBooks handles them natively: Receive payment for less than the balance, and the invoice stays open with the remainder. Every applied payment re-fires the loop from step 5, so the deal walks from Invoice created to Partially paid to Paid on its own, and Amount paid stays current the whole way. The only design decision was made back in step 3: a four-value status field instead of a checkbox.
Where this breaks: one payment, three invoices
A customer sends one e-transfer covering three open invoices, and the bookkeeper applies it across all three. QuickBooks records one payment with three linked transactions. A simple Zap reads only the first link, so one deal updates and two stay wrong. In Make, you loop over all linked transactions and update every matching deal. In Zapier, accept the gap and run a monthly cross-check: QuickBooks' open invoices report against your HubSpot unpaid deal view. Five minutes a month, and disagreements name themselves.
The acceptance test: how you know it worked
Run this list in order before telling anyone the system is live. Use a real product and a fake deal, on an afternoon when nobody is rushing you.
- Create a deal named QBO test, delete me with one line item and drag it to your trigger stage. Within two minutes the deal shows a QuickBooks invoice number and Invoice status reads Invoice created.
- Open QuickBooks. Exactly one invoice exists: right customer, right lines, a tax code on each line, total matching the deal amount.
- Drag the deal out of the stage and back in. Wait five minutes. Still exactly one invoice.
- In QuickBooks, use Receive payment to pay half the invoice. The deal flips to Partially paid with the correct Amount paid.
- Pay the remainder. The deal flips to Paid.
- Delete the test payments, invoice, and customer in QuickBooks, and the test deal in HubSpot. Then tell your bookkeeper you did this, so a stray test invoice never meets the GST filing.
Six of six is a pass. Five of six is a fail you have not found yet. The single most common miss is number 3, the duplicate test, because most people never think to test going backward.
When to stop DIYing, and what it costs if we do it
You do not need any automation if you send fewer than about 10 invoices a month and one person does the books. Connect the native integration, click Create invoice on the deal, done. One evening of setup, zero ongoing cost, and we will say the same thing on a call.
DIY the automation when you have one pipeline, one currency, line items that come from a product library, and someone in-house who is comfortable in Make or Zapier. With this guide it is a long Saturday, most of it spent on the acceptance test.
Bring in help when deposits or progress invoicing enter the picture, when you bill in more than one currency, when multiple pipelines need different rules, or when your accountant wants an audit trail they can defend. A build like the one above usually takes us 8 to 15 hours, so $1,200 to $2,250 at $150 per hour CAD, under our automation practice. The heavier versions, with deposits, credit notes, or multicurrency, run 15 to 25 hours, so $2,250 to $3,750. We quote the scope in writing before any clock starts, hours never expire, and there is no retainer. How we work covers the process. The worst outcome of a 30-minute call is that we tell you the native integration is enough, which it often is.
Frequently asked questions
Does this work with QuickBooks Desktop?
No. The native HubSpot integration, Zapier, and Make all talk to QuickBooks Online only. Desktop's realistic paths are its Web Connector with specialist middleware, or a migration to QuickBooks Online. If you are on Desktop and invoicing volume is the pain, the migration conversation usually comes before the automation conversation.
Can the native HubSpot integration create invoices automatically?
Not as of mid-2026. It creates an invoice only when a person clicks the button on a deal record. It is still worth connecting for contact sync, product sync, and read-only invoice visibility inside HubSpot. The automatic deal-stage trigger is exactly what Zapier or Make adds on top.
How do partial payments show up in HubSpot?
Through two custom deal properties: a four-value Invoice status dropdown and an Amount paid number. Every payment applied in QuickBooks re-fires the reconciliation automation, which checks the invoice's remaining balance. While a balance remains, the deal reads Partially paid with the running total. The deal only reads Paid when the QuickBooks balance hits zero.
What does it cost to have Tinyvation build this?
The standard build, deal-stage trigger plus line item mapping plus the reconciliation loop with partial payment handling, is usually 8 to 15 hours at a flat $150 per hour CAD, so $1,200 to $2,250. Deposits, credit notes, multicurrency, or multiple pipelines push it to 15 to 25 hours. Scope is quoted in writing first and hours never expire. Below about 10 invoices a month, we will tell you not to buy it.
Want this handled instead of read about?
We scope this exact work in hours, quote it in writing, and ship it in weeks. The 30-minute call is free and useful either way.
Book a 30-minute call$150/hr flat · published pricing · no retainer pitch