Clockify to GitHub, versioned time report backups
Time reports shouldn’t feel fragile. But when someone updates an entry after the fact (or a client questions a number), you’re stuck hunting through exports, screenshots, and “what did it say last week?” messages.
This is where Clockify GitHub backups start paying for themselves. Agency owners get fewer billing disputes, ops leads get cleaner month-end reporting, and consultants finally have a paper trail that doesn’t live in someone’s inbox.
This workflow automatically saves your Clockify monthly reports into a private GitHub repo as versioned files, so you can track edits over time and pull an audit-ready snapshot whenever you need it.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Clockify to GitHub, versioned time report backups
flowchart LR
subgraph sg0["Schedule Flow"]
direction LR
n0@{ icon: "mdi:cog", form: "rounded", label: "Extract from File", pos: "b", h: 48 }
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/compare.svg' width='40' height='40' /></div><br/>Compare Datasets"]
n2@{ icon: "mdi:location-exit", form: "rounded", label: "Stop and Error", pos: "b", h: 48 }
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "Globals", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set month indexes", pos: "b", h: 48 }
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out indexes", pos: "b", h: 48 }
n6@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set intervals", pos: "b", h: 48 }
n7@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Skip empty reports", pos: "b", h: 48 }
n8["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/clockify.dark.svg' width='40' height='40' /></div><br/>Get first workspace"]
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Get detailed monthly report"]
n10["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Check if file exists in GitHub"]
n11@{ icon: "mdi:swap-vertical", form: "rounded", label: "Point to new data", pos: "b", h: 48 }
n12@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check for 404 error message", pos: "b", h: 48 }
n13["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Update file in GitHub"]
n14["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Create file in GitHub"]
n15@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n3 --> n4
n6 --> n9
n1 --> n13
n15 --> n8
n0 --> n1
n11 --> n1
n4 --> n5
n5 --> n6
n7 --> n14
n8 --> n3
n12 --> n7
n12 --> n2
n9 --> n10
n10 --> n11
n10 --> n0
n10 --> n12
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n15 trigger
class n7,n8,n12 decision
class n9 api
classDef customIcon fill:none,stroke:none
class n1,n8,n9,n10,n13,n14 customIcon
The Problem: Time Reports Change After You Export Them
Clockify data is “live.” That’s great until it isn’t. People fix descriptions, shift time between projects, update tags, or log time late. Then your “final” monthly report is no longer final, and you’re left explaining why last month’s invoice doesn’t match this month’s export. It also creates quiet risk inside the business: leadership decisions get made from numbers that might drift, and nobody knows exactly when they changed. Frankly, this is how small errors become long, awkward threads.
The friction compounds. It shows up in a few predictable places:
- You export a report, then discover it was edited later, and now you can’t prove what the original said.
- Clients ask for a breakdown “as of invoice date,” and you’re rebuilding history from memory.
- Month-end admin turns into recurring detective work, especially when multiple people touch the same projects.
- There’s no clean diff of what changed, so disputes become opinion-based instead of evidence-based.
The Solution: Daily Versioned Backups of Clockify Monthly Reports
This workflow runs on a daily schedule and pulls your Clockify workspace reporting data via the Clockify Reports API. Instead of saving a single export that gets stale, it generates a report file for each month (by default, the current month plus the previous three). Then it checks your private GitHub repository to see if a file already exists for that month. If it does, the workflow compares the newly fetched report with the existing file and only updates GitHub when something actually changed. If the file is missing, it creates it, so your backups build themselves over time.
It starts with a scheduled run, grabs your primary workspace, and expands a small month list into individual month “batches.” Each batch computes the date range, requests the monthly detail report, and then either creates or updates a versioned file in GitHub. The end result is a commit history you can point to with confidence.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you manage one Clockify workspace and you export four monthly reports (current month plus three prior) every day during busy periods to keep invoices aligned. If each export, naming, and filing step takes about 5 minutes, that’s roughly 20 minutes a day. Over a month, you’re at about 10 hours of repetitive work. With this workflow, the “work” becomes a scheduled run and a few minutes to review GitHub only when you care to. The backups happen in the background, and your report history stays intact.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Clockify as the source of time entry reporting data.
- GitHub to store versioned monthly report files.
- Clockify API key (get it from your Clockify profile settings).
Skill level: Intermediate. You’ll connect credentials, create a private repo, and confirm a few report parameters like workspace and date ranges.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A daily schedule kicks things off. n8n runs the workflow automatically (daily by default), so backups stay current even when the team forgets about reporting.
Your Clockify workspace is identified. The workflow fetches the primary workspace first, then sets a few global values it uses throughout the run (like where to store files and which months to process).
Recent months are expanded into a short “to-do” list. It assigns month indices and splits them into individual items, then computes each month’s start and end date before requesting the detailed monthly report via HTTP.
GitHub becomes your source of truth for history. For each month, the workflow locates the matching file in GitHub, compares the newly fetched report to what’s already stored, and then updates or creates the file. Empty reports are filtered out so you don’t clutter the repo.
You can easily modify the number of months backed up to cover a longer window based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Scheduled Trigger
Set the schedule that starts the workflow each day.
- Add the Scheduled Run Trigger node and open its settings.
- Set the schedule rule to trigger at
triggerAtHour: 5so it runs daily at 5:00. - Connect Scheduled Run Trigger to Fetch Primary Workspace.
Step 2: Connect Clockify and Define Global Settings
Fetch the workspace and define global variables used across the workflow.
- Configure Fetch Primary Workspace with Resource set to
workspaceand Limit set to1. - Credential Required: Connect your
clockifyApicredentials in Fetch Primary Workspace. - In Define Globals, set workspace_id to
{{ $json.id }}. - In Define Globals, set github_repo.owner and github_repo.name to your GitHub owner and repository values.
- Connect Fetch Primary Workspace → Define Globals → Assign Month Indices.
Step 3: Build the Month Loop and Date Ranges
Create a rolling list of months and compute report ranges.
- In Assign Month Indices, set monthIndex to
[0, 1, 2]to process the current and previous two months. - In Expand Month List, set Field to Split Out to
monthIndex. - In Compute Date Range, set reportName to
=detailed_report_{{ $now.minus($json.monthIndex, 'month').format('yyyy-MM') }}. - Set startDate to
{{ $now.minus($json.monthIndex, 'month').startOf('month').format('yyyy-MM-dd') }}. - Set endDate to
{{ $now.minus($json.monthIndex, 'month').endOf('month').format('yyyy-MM-dd') }}.
Step 4: Request Clockify Reports and Locate GitHub Files
Fetch monthly report data and look up existing files in GitHub.
- In Request Monthly Detail, set URL to
https://reports.api.clockify.me/v1/workspaces/{{ $('Define Globals').item.json.workspace_id }}/reports/detailed. - Set Method to
POSTand JSON Body to{ "dateRangeStart": "{{ $json.startDate }}T00:00:00Z", "dateRangeEnd": "{{ $json.endDate }}T23:59:59.999Z", "detailedFilter": { "page": 1, "pageSize": 50 }, "exportType": "json" }. - Credential Required: Connect your
clockifyApicredentials in Request Monthly Detail. - In Locate GitHub File, set File Path to
reports/{{ $('Compute Date Range').item.json.reportName }}. - Credential Required: Connect your
githubApicredentials in Locate GitHub File. - Note the parallel flow: Locate GitHub File outputs to both Map New Report Data and Parse File Data in parallel.
Step 5: Compare Data and Update Existing Reports
Parse existing files, compare with new data, and update reports if needed.
- In Map New Report Data, set data to
{{ $('Request Monthly Detail').item.json.timeentries }}. - In Parse File Data, set Operation to
fromJsonto parse the file content. - In Compare Records, set Merge By Fields to compare
dataagainstdata. - In Modify GitHub File, set File Path to
reports/{{ $('Compute Date Range').item.json.reportName }}. - Set File Content to
{{ JSON.stringify($json.data, null, 2) }}and Commit Message toUpdate report. - Credential Required: Connect your
githubApicredentials in Modify GitHub File.
Step 6: Create New Reports When Files Are Missing
Handle missing files and only create reports when there is data.
- In Detect Missing File, confirm the condition checks
{{ $json.error }}containscould not be found. - In Filter Empty Reports, ensure the condition checks
{{ $json.timeentries }}isnotEmpty. - In Create GitHub File, set File Path to
reports/{{ $('Compute Date Range').item.json.reportName }}. - Set File Content to
{{ JSON.stringify($json.timeentries, null, 2) }}and Commit Message toCreate report. - Credential Required: Connect your
githubApicredentials in Create GitHub File.
Step 7: Add Error Handling
Stop the workflow when errors are not related to missing files.
- Verify Locate GitHub File has Continue On Fail behavior (it outputs to the error branch when the file is missing).
- Connect the false path of Detect Missing File to Halt on Error.
- In Halt on Error, set Error Message to
{{ $json.error }}.
Step 8: Test and Activate Your Workflow
Validate the run and turn on the schedule.
- Click Execute Workflow to run Scheduled Run Trigger manually.
- Confirm that Request Monthly Detail returns
timeentriesand that Locate GitHub File finds or routes missing files correctly. - Verify GitHub updates: Modify GitHub File should commit updated JSON, or Create GitHub File should create a new file under
reports/. - Set the workflow to Active to enable the daily run at 5:00.
Common Gotchas
- GitHub credentials can expire or need specific permissions. If things break, check the repo access token scopes and the n8n Credentials screen first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About 30 minutes once your API keys and repo are ready.
No. You’ll mostly connect accounts and paste API keys. The workflow logic is already built, so you’re configuring, not programming.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Clockify and GitHub usage, which is typically minimal for small monthly files.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, but you’ll want to adjust it thoughtfully. Change the month list in the “Assign Month Indices” and “Expand Month List” portion so it generates 12 items instead of 4. If you also rename files (for example, by client or by workspace), update the mapping step that prepares the GitHub filename before “Locate GitHub File.” Common tweaks include switching from daily to weekly runs, storing JSON instead of CSV, and writing to a different branch for approvals.
Usually it’s an expired or incorrect API key, so regenerate it in Clockify and update the credential in n8n. It can also be permissions related if the key doesn’t have access to the workspace you’re targeting. One more thing: make sure the Reports API endpoint you’re using matches your Clockify plan and that the workspace ID being fetched is the one you expect.
A lot more than most small teams need. On n8n Cloud Starter, you’re limited by monthly executions, but a once-daily run backing up four months is still pretty lightweight. If you self-host, there’s no execution limit (it depends on your server), and this workflow is mostly API calls plus file updates.
Often, yes, because the “compare then update” logic matters here and you don’t want to pay extra for multi-step branching. n8n is also comfortable with loops (processing multiple months in one run) and file comparison patterns that get awkward in simpler tools. Zapier or Make can still work if you only back up one export and don’t care about diffs, commits, or version history. If you need the audit trail to stand up in a client conversation, GitHub versioning is the whole point. Talk to an automation expert if you want help choosing the simplest setup.
Once this is running, time reports stop being a recurring fire drill. You get a living audit trail in GitHub, and you can get back to work that actually moves the business forward.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.