Expensify to QuickBooks Online Automated Reconciliation (n8n)

Seamlessly sync approved Expensify reports to QuickBooks Online using n8n's flexible node-based workflow.

Tools: ExpensifyQuickBooks

Platform: n8n

Short Answer

A fully automated pipeline that triggers upon report approval in Expensify, validates vendor data in QuickBooks, creates the appropriate Bill or Purchase, and attaches the original receipt image—ensuring 100% audit compliance without manual intervention.

The Problem

Manual entry of expense reports into accounting software is prone to human error and delays financial closing cycles. Businesses often struggle with missing receipt attachments and inconsistent vendor categorization between expense and accounting systems.

The Outcome

A fully automated pipeline that triggers upon report approval in Expensify, validates vendor data in QuickBooks, creates the appropriate Bill or Purchase, and attaches the original receipt image—ensuring 100% audit compliance without manual intervention.

Step-by-Step Guide

1. **Create Expensify Credentials**: In n8n, go to Credentials > New. You will need your Expensify `partnerUserID` and `partnerUserSecret`. Use the n8n Expensify node or a generic HTTP Request node for advanced API calls. 2. **Configure Trigger**: Add the 'Expensify' node and set the event to 'Report Approved'. If using the self-hosted n8n, ensure your Webhook URL is accessible via a public tunnel (like Cloudflare or ngrok). 3. **Extract Report Data**: Use an 'HTTP Request' node to call the `combinedReportData` export loop. Expensify requires a specific SQL-like syntax in the body to return JSON data. 4. **Split Expenses**: Add an 'Item Lists' node to split the 'expenses' array into individual items so n8n can process each line item separately. 5. **Sync Vendors**: Add a 'QuickBooks Online' node. Use the 'Vendor' resource and 'Get All' action. Use a filter expression: `{{ $json.merchant == $node.QuickBooks.vendor.DisplayName }}`. If no match is found, add a 'QuickBooks' node to 'Create' the vendor. 6. **Handle Receipts**: Add an 'IF' node to check if `receiptID` is present. If true, use an 'HTTP Request' node with 'Response Format: File' to download the receipt from the Expensify URL. 7. **Map to QuickBooks**: Add a 'QuickBooks Online' node (Action: Create Bill or Purchase). Map the amount, date, and vendor ID. Use expressions like `{{ $json.amount / 100 }}` to convert Expensify cents to QuickBooks decimals. 8. **Upload Attachment**: Link the binary output from the receipt download to a 'QuickBooks Online' node using the 'Attachment' resource. Reference the `ParentId` as the ID from the Bill created in the previous step. 9. **Global Error Handling**: Create a separate workflow or use the 'Error Trigger' node to catch failures (e.g., mapping errors or API timeouts) and notify the admin via Slack.

Data Mapping

| Expensify Field | QuickBooks Field | n8n Expression / Transformation | | :--- | :--- | :--- | | `merchant` | `VendorRef` | `{{ $node["Find Vendor"].json["Id"] }}` | | `amount` (cents) | `TotalAmt` | `{{ $json.amount / 100 }}` (Decimal conversion) | | `created` | `TxnDate` | `{{ $json.created.split(' ')[0] }}` (Extract YYYY-MM-DD) | | `category` | `AccountRef` | Match via lookup table or `Account` node | | `reportID` | `DocNumber` | `{{ $json.reportID }}` (For audit trail) | | `receipt_url` | `Attachment` | Requires 'HTTP Request' node set to 'File' response |

Gotchas & Failure Modes

* **Expensify Cents vs QBO Decimals**: Expensify returns amounts as integers (cents). You MUST divide by 100 in n8n expressions or your accounting will be 100x off. * **Rate Limiting**: QuickBooks API has a limit of 500 requests per minute. Use the n8n 'Wait' node or 'Split in Batches' if processing reports with hundreds of line items. * **Binary Data Management**: When downloading receipts, ensure the 'Property Name' in the HTTP Request node matches the 'Input Data Property' in the QuickBooks Attachment node (usually `data`). * **OAuth Refresh**: n8n handles QBO OAuth refreshes, but ensure your instance is running a recent version to avoid token expiration bugs during long periods of inactivity.

Verification Checklist

- [ ] Trigger a 'Test Step' in the Expensify node by manually approving a dummy report. - [ ] Check the 'Binary' tab in n8n execution data to confirm receipts are being downloaded correctly. - [ ] Verify in QuickBooks Sandbox that the 'Vendor' ID matches the merchant name exactly to prevent duplicates. - [ ] Validate that the 'Total Amount' in QBO matches the 'Total Amount' in Expensify after the decimal conversion. - [ ] Check n8n 'Execution Log' for any 401 (Unauthorized) errors, indicating credential refresh issues.

Ready to Automate?

Build this automation with n8n in minutes.