Short Answer
A seamless, real-time sync where 'Won' opportunities in GoHighLevel trigger the creation or update of a QuickBooks customer and the generation of a corresponding invoice with accurate line items and tax data.
The Problem
Manual data entry between CRM sales stages and accounting software leads to invoicing delays, human error in line-item pricing, and fragmented financial reporting. Sales teams often forget to notify accounting when a deal is closed, resulting in stalled cash flow.
The Outcome
A seamless, real-time sync where 'Won' opportunities in GoHighLevel trigger the creation or update of a QuickBooks customer and the generation of a corresponding invoice with accurate line items and tax data.
Step-by-Step Guide
1. **Create Scenario**: In Make.com, create a new scenario and add the **GoHighLevel (GHL)** module with the 'Watch Opportunities' trigger. Create a 'Webhook' and copy the URL into a GHL Workflow (Trigger: Opportunity Status Changed to Won -> Action: Webhook).
2. **Establish Connections**: Authenticate GHL via API Key/OAuth and QuickBooks Online via OAuth2. Ensure you have 'Company Admin' rights in QuickBooks.
3. **Search Customer**: Add a **QuickBooks Online** 'Search for Customers' module. Use the `Email` from the GHL bundle as the search criteria (Query: `PrimaryEmailAddr = '{{1.contact.email}}'`).
4. **Add Router**: Place a Router module after the search. This allows the logic to bifurcate based on whether the customer was found.
5. **Create/Update Customer Path**:
- **Path A (Customer Not Found)**: Set a filter `Total number of bundles` equal to 0. Add 'Create a Customer' module.
- **Path B (Customer Found)**: Set a filter `Total number of bundles` greater than 0. Add 'Update a Customer' module using the `ID` from the search result.
6. **Map Line Items**: Add a **QuickBooks Online** 'Create an Invoice' module. Since GHL might send multiple products, use the `map()` function or an **Iterator** if GHL returns an array of products to build the `Line` items array for the invoice.
7. **Define Revenue Account**: In the 'Create Invoice' module, manually select or map the `Income Account ID` (e.g., 'Sales of Product Income'). This is a required field in QuickBooks API.
8. **Error Handling**: Right-click the QuickBooks modules and select 'Add error handler'. Use a **Break** module to retry on temporary API timeouts or a **Rollback** if the data is malformed.
9. **Feedback Loop**: Add a final **GHL** 'Add Tag to Contact' module to tag the lead as 'Invoiced' or 'QB-Synced' to prevent duplicate triggers.
Data Mapping
| GHL Source Field | QuickBooks Field | Transformation / Logic |
| :--- | :--- | :--- |
| `Contact.Name` | `DisplayName` | `{{1.contact.first_name + " " + 1.contact.last_name}}` |
| `Contact.Email` | `PrimaryEmailAddr` | Required for deduplication check |
| `Opportunity.Value` | `Line: Amount` | `{{parseNumber(1.value)}}` |
| `Opportunity.ID` | `PrivateNote` | Store GHL ID for cross-referencing |
| `N/A (Fixed)` | `ItemRef` | Use Map to link to a fixed QB Service ID (e.g. "1") |
| `Current Date` | `TxnDate` | `{{formatDate(now; "YYYY-MM-DD")}}` |
Gotchas & Failure Modes
* **Account IDs vs Names**: QuickBooks API requires the internal `ID` for accounts and items, not the display name. Use a 'List Accounts' module once during setup to find the correct ID.
* **Bundle Aggregation**: If a GHL Opportunity has multiple products, you MUST use an 'Array Aggregator' before the QB Invoice module to prevent Make from creating five separate invoices for five separate products.
* **Rate Limits**: QuickBooks has a limit of 100 requests per minute. Use Make's 'Sleep' module or 'Scenario Settings' to limit concurrency if processing bulk historical data.
* **Tax Codes**: If tax is required, the `TaxCodeRef` must be active in QuickBooks; otherwise, the module will return a 'Validation Exception'.
Verification Checklist
- [ ] **Webhook Check**: Trigger a 'Won' status in GHL and verify the 'Watch Opportunities' module receives a bundle in the Make.com execution log.
- [ ] **Deduplication Test**: Run the scenario with an email address already in QB; ensure it updates the record instead of creating a duplicate.
- [ ] **Line Item Accuracy**: Verify that the Opportunity Value in GHL matches the 'Total Amount' in the generated QB Invoice.
- [ ] **Error Handler Test**: Temporarily disconnect the QB module and ensure the error handler captures the failure without stopping the scenario (if using the 'Break' directive).
Ready to Automate?
Build this automation with Make.com in minutes.