Stop chasing freelancers for hours at the end of the month
Short answer: don't automate "send the timesheet to accounting". Automate the four steps around it: pull the hours, find who is missing or odd, nudge only those people, and hold everything for one human approval before a single, de-duplicated push to accounting. Most of the pain is the chasing, not the copying.
This came up on r/automation on 4 November 2026 ("How do you automate your end-of-month timesheet reporting?"), where the poster pulls hours from a time tracker into accounting with Zapier and still ends up chasing people. Here is a tool-neutral pattern you can build in n8n, Make or Zapier.
The workflow in five steps
| Step | Trigger / node | What it does |
|---|---|---|
| 1. Roster | Sheet or database | One row per person: name, email, tracker user ID, expected hours, rate, approver |
| 2. Pull | Schedule (e.g. 2 working days before month end) | Read each person's logged hours for the period from the tracker's API or export |
| 3. Check | Code / filter | Flag people with 0 hours, hours far from expected, or entries still running |
| 4. Nudge | Email / Slack / Telegram | Message only the flagged people, with their current total and a deadline |
| 5. Approve and push | Approval step, then accounting | After a human approves, send one invoice or bill per person, keyed so it can't be created twice |
Step 3: the check is where the value is
A useful first version flags only three things:
- Missing: no hours logged for the period.
- Out of range: logged hours differ from expected by more than a threshold you choose (for example 20%).
- Open entries: a timer that was never stopped, which inflates totals.
Everyone else goes straight to the approval list. That way the reminder email reaches the two or three people who need it, not the whole team.
Step 4: nudges that people actually answer
- Send it from a real person's address or channel, not a no-reply.
- Include their current number: "You have 96.5 hours logged for October. Please fix or confirm by Friday 12:00."
- Re-run steps 2 and 3 before each reminder so people who already fixed it don't get pinged again.
- Cap reminders (two is usually enough) and escalate the rest to the approver.
Step 5: approve once, push once
Accounting is the side effect you can't undo, so treat it carefully:
- Write the final totals to an "approval" sheet or table with a status column.
- A manager marks each row approved (or approves the whole batch).
- The push step only reads approved rows and builds a key such as
timesheet:2026-10:<person_id>. - Before creating the bill or invoice, check that key in a small table or data store. If it exists, skip.
This is the same idempotency idea from our earlier post on safe retries: a retried run, or someone clicking "run" twice, must not create two bills.
Common mistakes
- Pulling on the last day. Run the first pull a couple of working days early so there is time to fix gaps.
- Rounding before summing. Sum raw durations, then round once.
- Time zones. Define the period in one time zone; a remote worker's late-night entry can land in the wrong month otherwise.
- No audit trail. Keep the approved snapshot. If a number is disputed later, you need what was approved, not what the tracker says today.
n8n or Make?
Both handle this well. n8n is a good fit if you already self-host and like writing the check step in a Code node. Make's scheduler, routers and Data Store cover the same steps without code; you can try it on the free plan here: Make free plan.
Disclosure: Some links are affiliate links — I may earn a commission at no extra cost to you.
Top comments (0)