Automated Expensify Report Sync to Xero Purchase Bills (Make.com)

Streamline employee reimbursements by automatically converting approved Expensify reports into Xero bills with full receipt attachments via Make.com.

Tools: ExpensifyXero

Platform: Make.com

Short Answer

A seamless, hands-free workflow where any 'Approved' report in Expensify instantly generates a 'Draft/Awaiting Payment' Bill in Xero. This ensures 100% data accuracy, automated receipt filing, and real-time visibility into company liabilities.

The Problem

Manual entry of expense reports into accounting software is prone to human error, creates significant administrative overhead, and delays employee reimbursements. Without automation, matching receipt images to specific GL codes in Xero becomes a bottleneck during month-end closing.

The Outcome

A seamless, hands-free workflow where any 'Approved' report in Expensify instantly generates a 'Draft/Awaiting Payment' Bill in Xero. This ensures 100% data accuracy, automated receipt filing, and real-time visibility into company liabilities.

Step-by-Step Guide

1. **Create Scenario**: Log into Make.com, click 'Create a new scenario', and name it 'Expensify to Xero Bill Sync'. 2. **Configure Expensify Trigger**: Add the **Expensify > Watch Reports** module. Create a connection using your Partner User ID and Partner User Secret. Set the trigger to watch for status changes to 'Approved'. 3. **Add Filter**: Click the line between the Expensify module and the next step. Name it 'Only Sync Approved'. Set the condition where `Status` (from Expensify) matches `Approved` (or `Reimbursed` depending on your policy). 4. **Download Receipts (HTTP)**: Add an **HTTP > Get a File** module. Map the `Receipt URL` from Expensify to the URL field. This allows Make to pass the actual binary file to Xero rather than just a text link. 5. **Xero Contact Step**: Add a **Xero > Search for Contacts** module. Search by the name/email of the merchant or employee. Use a **Router** or **IF/ELSE** logic to create the contact if it does not exist. 6. **Map the Purchase Bill**: Add the **Xero > Create a Purchase Bill** module. - **Contact**: Map the ID from the previous step. - **Date**: Use the Make.com `formatDate()` function to ensure the Expensify date matches Xero’s format: `formatDate(raw_date; YYYY-MM-DD)`. - **Line Items**: Use the Expensify `Expenses[]` array. Map `Amount`, `Comment`, and use a `switch()` function to map Expensify Categories to Xero Account Codes. 7. **Upload Attachment**: Add the **Xero > Upload an Attachment** module. Select 'Purchase Bill' as the object type, map the Bill ID from the previous step, and use the 'Data' from the HTTP module as the file source. 8. **Error Handling**: Right-click the Xero module and select **Add error handler**. Use a 'Break' directive to retry the operation or a 'Send Email' module to notify you if the Chart of Accounts mapping fails.

Data Mapping

| Expensify Field | Xero Destination Field | Make.com Transformation/Logic | | :--- | :--- | :--- | | `Report ID` | Reference | `Report ID: {{item.reportID}}` | | `Total` | Line Amount | `{{item.total / 100}}` (if cents) or Raw | | `Category` | Account Code | `switch(category; Travel; 450; Meals; 420; 400)` | | `Created Date` | Date | `formatDate(created; YYYY-MM-DD)` | | `Currency` | Currency Code | `{{item.currency}}` | | `Receipt URL` | File Content | Downloaded via **HTTP Get a File** module | | `Employee Email` | Contact / Description | Map to Xero Contact ID via Search module |

Gotchas & Failure Modes

* **Account Code Mapping**: Expensify uses names (e.g., 'Travel'), but Xero API requires unique codes (e.g., '450'). Always use a `switch()` function or a 'Data Store' in Make to bridge this gap. * **Rate Limiting**: Xero has a limit of 60 calls per minute. If processing 100+ expenses at once, use the **Sleep** module or set the Scenario's 'Max number of cycles' to a lower number. * **Currency Mismatch**: Ensure 'Multi-currency' is enabled in Xero if Expensify reports contain non-base currency items, otherwise the API will return a 400 error. * **Binary Data**: You cannot simply map a URL to Xero's attachment field. You must use the 'HTTP' module to 'Get a File' first to handle the binary stream.

Verification Checklist

- [ ] **Run Once**: Use the 'Run Once' button and manually trigger an approval in Expensify. - [ ] **Data Check**: Verify the Bill appears in Xero under 'Purchases > Draft'. - [ ] **Receipt Check**: Open the Xero Bill and ensure the 'File' icon shows the correct receipt attachment. - [ ] **Filter Validation**: Ensure an 'Open' or 'Submitted' report does NOT trigger a Xero entry. - [ ] **Mapping Check**: Check that the Tax Rate and Account Code in Xero align with your Chart of Accounts.

Ready to Automate?

Build this automation with Make.com in minutes.