Automated Sales Invoice Generation from Google Sheets (Make.com)

Eliminate manual bookkeeping by automatically syncing 'Closed-Won' deals from Google Sheets to Xero Invoices.

Tools: Google SheetsXero

Platform: Make.com

Short Answer

A seamless, real-time bridge where a status change in Google Sheets instantly creates or updates a Contact in Xero and generates a Draft Invoice. This ensures 100% data accuracy and provides immediate visibility into accounts receivable.

The Problem

Sales teams often manage pipelines in flexible spreadsheets, leading to manual data entry errors and delays when transitioning deals to the finance department for invoicing. This disconnect creates friction in the cash flow cycle and increases the risk of duplicate or missed billings.

The Outcome

A seamless, real-time bridge where a status change in Google Sheets instantly creates or updates a Contact in Xero and generates a Draft Invoice. This ensures 100% data accuracy and provides immediate visibility into accounts receivable.

Step-by-Step Guide

1. **Create Scenario**: Log in to Make.com, click 'Create a new scenario', and add the **Google Sheets > Watch Changes** (Instant) module. 2. **Connect Google Sheets**: Click 'Add' to create a connection. Install the 'Make for Google Sheets' Add-on in your sheet, paste the provided Webhook URL, and select the specific spreadsheet and worksheet. 3. **Set Up Filter**: Add a Filter between the Google Sheets and Xero modules. Set the condition to only proceed if the 'Status' column (e.g., Column C) `Equal to` 'Closed-Won' AND 'Xero Invoice ID' `Does not exist` (to prevent duplicates). 4. **Search Contact**: Add the **Xero > Search for a Contact** module. Map the 'Email' field from the Sheet to the 'EmailAddress' search field. This prevents creating duplicate contacts for returning customers. 5. **Router for Logic**: Add a **Router**. On the first path, set a filter: `Contact ID` (from search) `Does not exist`. Add the **Xero > Create a Contact** module here. 6. **Create Invoice**: Add the **Xero > Create an Invoice** module after the Router paths converge. Map the Contact ID (from either search or create), and fill the Line Items using fields like `Description`, `Quantity`, and `UnitAmount` from the Sheet. 7. **Data Formatting**: Use the Make.com `parseDate()` function for the Invoice Date to ensure it's in ISO 8601 format (e.g., `parseDate(DateColumn; "MM/DD/YYYY")`). 8. **Update Source**: Add a **Google Sheets > Update a Row** module. Map the Original Row ID and write the Xero Invoice ID back to a 'Xero Link' column. This acts as a 'Processed' flag. 9. **Error Handling**: Right-click the Xero Invoice module and select 'Add error handler'. Choose the **Break** or **Rollback** directive, or add a **Slack** module to notify the admin if an Account Code is invalid.

Data Mapping

| Google Sheets Field | Xero API / Mapping Syntax | Requirement | Notes | | :--- | :--- | :--- | :--- | | Customer Email | `{{1.EmailAddress}}` | Required | Used for 'Search Contact' lookup | | Status | `{{1.Status}}` | Required | Filter: proceeds only if 'Closed-Won' | | Account Code | `{{ifempty(1.AccountCode; "200")}}` | Required | Must match Xero Chart of Accounts | | Units | `{{toNumber(1.Quantity)}}` | Required | Ensure numeric format using `toNumber()` | | Date | `{{formatDate(1.Date; "YYYY-MM-DD")}}` | Required | Xero requires YYYY-MM-DD format | | Tax Rate | `{{1.TaxType}}` | Optional | Must match Xero Tax Rates (e.g., 'OUTPUT') |

Gotchas & Failure Modes

* **Data Types**: Xero will reject 'Quantity' or 'UnitAmount' if they are passed as strings. Always wrap your Google Sheet variables in the `toNumber()` function in the mapping panel. * **Rate Limits**: Xero's API has a limit of 60 requests per minute. If processing bulk rows (e.g., via the 'Watch Rows' module rather than Webhooks), use the 'Sleep' tool or set the Scenario 'Max number of bundles' to a low value. * **Account Codes**: Xero expects the internal Code (e.g., 200), not the name (e.g., 'Sales'). Use Data Validation in Google Sheets via a dropdown to ensure only valid codes are entered. * **OAuth Refresh**: Xero connections in Make.com may occasionally expire if the scenario is inactive for 60+ days. Check your connection status if the scenario stops unexpectedly.

Verification Checklist

- [ ] **Webhook Check**: Trigger a change in the Sheet and verify the 'Watch Changes' module receives the bundle in the Make.com log. - [ ] **Filter Check**: Ensure the scenario stops if the status is NOT 'Closed-Won'. - [ ] **Data Formatting**: Check the Xero module output to see if dates and numbers are formatted correctly (no extra spaces or currency symbols). - [ ] **Duplicate Logic**: Run the scenario twice for the same row; verify the second run is stopped by your filter to prevent duplicate invoices. - [ ] **Write-back**: Confirm the Xero Invoice ID is successfully written back to the Google Sheet column.

Ready to Automate?

Build this automation with Make.com in minutes.