Automated FreshBooks Invoicing from Clockify Time Entries (n8n)

Streamline billing by automatically synchronizing tracked billable hours into FreshBooks draft invoices using n8n.

Tools: ClockifyFreshBooks

Platform: n8n

Short Answer

Users get a fully automated bridge where every stopped timer in Clockify immediately creates or updates a record in FreshBooks. This ensures 100% billing accuracy, consistent project naming conventions, and real-time visibility into pending revenue without manual intervention.

The Problem

Manual data entry between time trackers and accounting software often leads to 'leaky' billable hours, incorrect rate applications, and administrative burnout. Small agencies and freelancers frequently lose hours of productive time simply re-typing Clockify descriptions into FreshBooks invoice lines.

The Outcome

Users get a fully automated bridge where every stopped timer in Clockify immediately creates or updates a record in FreshBooks. This ensures 100% billing accuracy, consistent project naming conventions, and real-time visibility into pending revenue without manual intervention.

Step-by-Step Guide

1. **Establish Credentials**: In n8n, go to 'Credentials' and add 'Clockify API' (using your API Key from Profile Settings) and 'FreshBooks OAuth2' (requires creating an app in the FreshBooks Developer Portal). 2. **Configure Clockify Trigger**: Add the 'Clockify Trigger' node. Set the 'Resource' to 'Time Entry' and 'Event' to 'Created'. Ensure the 'Workspace ID' is correctly selected. 3. **Add Filter Node**: Connect an 'IF' node to check if `{{ $node["Clockify Trigger"].json["billable"] }}` is equal to `true`. This prevents non-billable internal work from cluttering your accounting. 4. **Data Transformation (Duration)**: Clockify sends duration as an ISO 8601 string or seconds. Add a 'Code' node to convert this to decimal hours for FreshBooks using: `return [{ json: { hours: (item.json.timeInterval.duration_seconds / 3600).toFixed(2) } }];`. 5. **Client Look-up**: Add a 'FreshBooks' node, action 'Get Many' for 'Client'. Use a 'Filter' or n8n expression to match the Clockify client name/email with existing FreshBooks records. 6. **Logical Branching**: Add an 'IF' node to check if the FreshBooks Client ID exists. If not, add another FreshBooks node to 'Create Client'. 7. **Create Time Entry/Invoice Item**: Add a FreshBooks node. Select the action 'Create' for the 'Time Entry' resource. Map the decimal hours from Step 4 and the description from Step 2. 8. **Duplicate Handling**: Use a 'Wait' node or a 'Check Document' step if syncing in batches to ensure the same `clockify_id` hasn't been processed in the last 60 seconds. 9. **Error Handling**: Create an 'Error Trigger' workflow or use the 'On Error' -> 'Continue' setting on the FreshBooks node to catch API rate limits. 10. **Enable Workflow**: Save the workflow and toggle the 'Active' switch. n8n will now listen for the Clockify Webhook.

Data Mapping

| Data Field (Clockify) | Data Field (FreshBooks) | n8n Expression / Transformation | Required? | | :--- | :--- | :--- | :--- | | `description` | `note` | `{{ $json.description or 'No description' }}` | Yes | | `timeInterval.duration` | `hours` | `{{ $json.timeInterval.duration_seconds / 3600 }}` (Decimal) | Yes | | `clientId` | `client_id` | Match via FreshBooks Search Node | Yes | | `projectId` | `project_id` | `{{ $json.projectId }}` (Mapped via ID lookup) | Optional | | `startTime` | `date` | `{{ $json.timeInterval.start.split('T')[0] }}` | Yes |

Gotchas & Failure Modes

* **The Seconds Trap**: Clockify provides duration in seconds; FreshBooks expects decimal hours. Always use an n8n Expression or Code node to divide by 3600. * **Rate Limiting**: If you use a 'Split in Batches' node for historical syncs, set it to 50 items per minute to avoid FreshBooks' API throttling. * **Workspace Mismatches**: Ensure the API Key used in n8n has access to the specific Workspace ID selected in the node; otherwise, the trigger will silently fail. * **Client ID Sync**: n8n requires the internal FreshBooks `client_id` (integer), not the client name. You MUST use a 'Get Many' or 'Search' node before creating entries.

Verification Checklist

- [ ] Trigger a test 'New Time Entry' in Clockify by stopping a 1-minute timer. - [ ] Check n8n 'Executions' tab to verify the webhook was received. - [ ] Confirm the Code node correctly converted seconds (e.g., 3600s) to 1.00 hours. - [ ] Verify in FreshBooks that a 'Time Entry' or 'Draft Invoice' appeared under the correct client. - [ ] Use n8n 'Wait' or 'Limit' nodes if testing with more than 10 entries at once to prevent race conditions.

Ready to Automate?

Build this automation with n8n in minutes.