Time Tracker to QuickBooks Online Automation (n8n)
Seamlessly sync billable hours to QuickBooks using n8n's robust node-based workflow and error handling.
Tools: Time Tracker → QuickBooks
Platform: n8n
Short Answer
A fully automated pipeline where approved time entries trigger real-time 'TimeActivity' creation in QuickBooks. The workflow includes automated customer lookups and data formatting, ensuring every billable minute is accurately accounted for without manual intervention.
The Problem
Manual entry of billable hours from time tracking tools into QuickBooks is prone to human error, leading to billing discrepancies and delayed invoicing. Businesses often struggle to map external project IDs to QuickBooks Customer equivalents, resulting in fragmented financial records.
The Outcome
A fully automated pipeline where approved time entries trigger real-time 'TimeActivity' creation in QuickBooks. The workflow includes automated customer lookups and data formatting, ensuring every billable minute is accurately accounted for without manual intervention.
Step-by-Step Guide
1. **Establish Credentials**: In n8n, navigate to 'Credentials' and set up 'QuickBooks Online OAuth2'. For your Time Tracker (e.g., Toggl/Clockify), use the respective predefined node or an 'Header Auth' for a Webhook/API.
2. **Configure Trigger**: Add a 'Webhook' node or the Time Tracker specific node. Set the event to 'New Time Entry' or 'Time Entry Stopped'. Set the 'HTTP Method' to POST.
3. **Sanitize Data**: Add an 'Edit Fields' (formerly Set) node. Use expressions like `{{ $json.duration / 3600 }}` to convert seconds to hours, and format dates using `{{ $now.format('YYYY-MM-DD') }}`.
4. **Customer Lookup**: Add a 'QuickBooks Online' node. Set the Resource to 'Account' and Operation to 'Get All'. Use a Query inside the node: `SELECT * FROM Customer WHERE DisplayName = '{{ $json.projectName }}'`.
5. **Routing Logic**: Add an 'If' node to check if the Customer Lookup returned an ID. Expression: `{{ $node["QuickBooks"].json["Id"] ? true : false }}`.
6. **Create Missing Customer (Optional)**: If 'false', route to another QuickBooks node set to Resource: 'Customer', Operation: 'Create'.
7. **Create TimeActivity**: Add a QuickBooks node set to Resource: 'Time Activity', Operation: 'Create'. Map the `CustomerRef` to the ID found in step 4 or 6. Map `Description` to the task name and `TxnDate` to the entry date.
8. **Data Transformation**: Use an 'Expression' in the HourlyRate field: `{{ parseFloat($json.rate) || 0 }}` to ensure the data type matches QuickBooks' expectation of a number.
9. **Initialize Error Handling**: Create a separate workflow with an 'Error Trigger' node. Connect it to a Slack or Email node to notify you if the QuickBooks API returns a 400 or 401 error.
10. **Enable Node Retries**: In the QuickBooks node settings, enable 'Retry on Fail' with a 3-repetition limit to handle temporary network blips.
Data Mapping
| Source Field (Time Tracker) | QuickBooks Field | n8n Expression / Transformation |
| :--- | :--- | :--- |
| `description` | `Description` | `{{ $json.description }}` |
| `duration` (sec) | `Hours` | `{{ $json.duration / 3600 }}` (Decimal) |
| `start_date` | `TxnDate` | `{{ DateTime.fromISO($json.start).toFormat('yyyy-MM-dd') }}` |
| `project_id` | `CustomerRef` | Reference from Lookup Node: `{{ $node["Lookup"].json["Id"] }}` |
| `is_billable` | `BillableStatus` | `{{ $json.billable ? 'Billable' : 'NotBillable' }}` |
| `user_email` | `EmployeeRef` | Requires a mapping table or static ID lookup in n8n |
Gotchas & Failure Modes
• **Rate Limiting**: QuickBooks Online has a limit of 40 requests per minute. Use n8n's 'Wait' node if processing large batches of historical time entries.
• **Data Types**: QuickBooks strictly requires numbers for 'Duration'. Ensure you use `parseFloat()` in your expressions to avoid 'Type Mismatch' errors.
• **SyncTokens**: If updating existing entries, you must fetch the latest `SyncToken` from QuickBooks first, or the update node will fail.
• **Customer Mapping**: If your Tracker uses 'Project Names' and QuickBooks uses 'Client Names', ensure they match exactly or use an n8n 'Switch' node to map IDs manually.
Verification Checklist
- [ ] Run a 'Test Step' on the Trigger node using a real-time entry from your tracker.
- [ ] Check n8n 'Execution Details' to verify the SQL query in the QuickBooks lookup node returns the correct ID.
- [ ] confirm the 'TimeActivity' appears in QuickBooks under 'Reports > Unbilled Time'.
- [ ] Intentionally trigger an error (e.g., provide a 0 duration) to ensure the Error Trigger workflow fires.
- [ ] Verify that the 'SyncToken' is not required for 'Create' operations (only for Updates).
Ready to Automate?
Build this automation with n8n in minutes.