Invoice and Timesheet Automation With n8n Plus Google Workspace
The exact flow: WhatsApp or Slack message to a Google Sheet timesheet to a monthly PDF invoice emailed to the client. What we built for an agency moving off manual timesheets.
Every agency we audit has two spreadsheets that cost more than they should. One is the timesheet that nobody logs hours into until the last Friday of the month, and the other is the invoice template that the founder fills in by hand while reconstructing what each freelancer actually did. The gap between the work happening and the work being billed is where margin quietly disappears. Forgotten hours, rounded-down estimates, late invoices that push cash collection into the next month, clients disputing line items that were written from memory three weeks after the fact.
The fix is not a better spreadsheet. The fix is to move hour capture to the place where your team already talks, and to move invoice generation to a scheduled job that fires on the first of the month whether anyone remembers or not. This article is the exact n8n workflow we built for an agency of fourteen people who were losing roughly twelve billable hours a month to manual timesheet gaps and pushing invoices out an average of nine days late. After the build the gaps closed and invoices left on day one every month.
Why WhatsApp or Slack Is the Right Capture Surface
The reason timesheets fail is not laziness. It is context switching. A designer in Figma or a developer in Cursor is not going to pause their flow, open a browser tab, find the timesheet app, remember the project code, pick the right row, and type. They will do it at the end of the week from memory and round generously or stingily depending on their mood. Either way the data is wrong.
The capture surface has to be where the hands already are. For most of our agency clients that is Slack during work hours and WhatsApp on the phone. A freelancer finishing a two-hour block for a client can type a single message like ACME 2h homepage hero revisions and move on. The discipline required is one sentence. That is the only cognitive load a timesheet system should impose.
The interesting engineering problem is turning that one sentence into structured data that a sheet can hold. You cannot require a rigid format, because people will get it wrong and stop using the system. You need to accept a loose natural language message and extract the project code, the hours, and the notes reliably. This is the chat-input to sheet-row pattern, and it is the piece most search results on invoice automation miss entirely. They show you a form that writes to a sheet, which solves nothing because the friction of the form is exactly the thing that broke the old timesheet.
The Chat-Input to Sheet-Row Pattern in n8n
In n8n the workflow starts with two parallel triggers. One is the Slack trigger set to listen on a private channel called #timesheet. The other is a WhatsApp Business Cloud webhook pointed at a dedicated number. Both triggers feed into a Set node that normalizes the incoming payload to three fields: sender, text, and timestamp. From that point on the flow does not care where the message came from.
The next node is the parser, and this is where Claude earns its keep. We route the text field into an Anthropic node with a system prompt that tells the model to extract four values from any message about worked hours: client code, hours worked as a decimal number, a short description, and a date if mentioned, defaulting to today. The prompt includes three or four few-shot examples showing messy real inputs like 2.5h on acme, hero section and nav fixes or did 45 min on bloomco call yesterday. The output is forced into JSON using structured output so that the downstream nodes do not have to guess at the shape.
Before appending to the sheet we pass the extracted payload through an IF node that checks two things. First, that the client code matches one of the active projects in a reference sheet. If it does not, the flow routes to a Slack DM back to the sender asking for clarification, which is much friendlier than a silent failure. Second, that the hours value is between zero and twelve. Anything above twelve is almost certainly a typo, and we flag it rather than record it.
When the payload passes both checks the Google Sheets node appends a row to the monthly timesheet. The sheet has seven columns: date, sender, client code, hours, description, source, and a status field that starts at logged. The status field becomes important later when invoices are generated and we need to mark rows as billed so they do not get billed twice.
The Reference Data That Holds This Together
A second Google Sheet holds the project reference data. Each row has a client code, the full client name, the billing email, a rate, a currency, and a billing cadence. Every decision downstream reads from this sheet rather than from hardcoded values inside n8n, which is the difference between a workflow you can hand to an operations person and a workflow that only the person who built it can edit.
When a new client is added the operations lead fills a row in this sheet and the next invoice cycle picks them up automatically. No n8n edits required. This is the pattern we push all non-technical founders toward when they work with us. Build the plumbing in n8n, but keep every piece of data a human might want to change inside a spreadsheet they already know how to edit.
A third sheet holds a running invoice log, one row per invoice, with the invoice number, client code, period, total, PDF link, send date, and paid date. This sheet becomes the source of truth for accounts receivable. Because every row links to a PDF in Google Drive, the founder can audit any invoice without opening a separate billing system.
Generating the Monthly PDF With a Google Docs Template
The invoice generator is a separate n8n workflow on a cron schedule. It fires at seven in the morning on the first of every month. The first node pulls the client reference sheet and filters for any client on a monthly cadence. For each client the flow pulls all rows from the timesheet sheet where the client code matches, the date falls inside the previous month, and the status equals logged.
This is where most DIY attempts get stuck. You can generate a PDF by building HTML and piping it through a headless browser, but the output looks engineered and your clients notice. The better path is to keep a real Google Docs invoice template that your brand designer actually designed, and use the Google Docs API to copy the template and replace merge tags inside it. n8n has a Google Docs node that supports exactly this.
The template holds placeholders like {{client_name}}, {{invoice_number}}, {{period}}, {{line_items}}, {{subtotal}}, {{tax}}, and {{total}}. The workflow copies the template to a client folder in Drive, renames it to include the invoice number, and runs a batchUpdate call that swaps each placeholder for its value. The line items placeholder is the trickiest because it is a table. The approach that works is to build the rows as a single multi-line string with tab separators, let Docs render them inside a pre-existing table shell, and accept that the formatting is slightly less rich than a true generated table. For ninety percent of agency invoices this is more than enough.
After the document is populated the flow exports it as a PDF through the Drive API, uploads the PDF to a per-client invoices folder, and writes the PDF link into the running invoice log sheet. The Google Doc stays in Drive as an editable version in case a number needs to change after sending, which happens more often than you expect. Nothing is ever regenerated from scratch. If you need to correct a hour count you edit the timesheet row, rerun a dry-run branch of the workflow, and replace the PDF.
The Approval Step Before the Email Goes Out
This is the piece that separates a system people will trust from one that scares them. Even when the automation works perfectly the founder wants to look at the invoice before it hits the client. Shipping a wrong invoice to a client is worse than shipping a late invoice, so there has to be a human checkpoint that cannot be skipped.
After the PDF is generated the workflow posts a message into a private Slack channel called #invoices-review. The message includes the client name, the period, the total, the PDF link with a preview, and two interactive buttons labeled Approve and Send and Reject. The workflow uses n8n's Wait node set to resume on a webhook, which means the execution pauses indefinitely until a human clicks one of the buttons.
If the founder clicks approve, the webhook fires back into n8n and the flow proceeds to the email node. If the founder clicks reject, the Slack bot asks for a reason in a thread, writes the reason into a rejection log, and halts. The PDF stays in Drive, the timesheet rows stay at status logged, and nothing is marked billed. The founder can fix the underlying data and rerun the workflow for that single client from a manual trigger.
The approval step typically takes under thirty seconds per client. For an agency with twenty active clients that is ten minutes of founder time per month spent on billing. Compared to the three to four hours the same founder was spending before, this is the change that actually sticks. The automation does the work. The human does the judgment. Neither is asked to do the other's job.
Email Delivery With the Attachment and the Follow-Up Chain
Once approved, the flow moves to the Gmail node. We use Gmail over a transactional email service like Postmark because invoice emails should come from the human who owns the client relationship, not from a no-reply address. The Gmail node authenticates with a service account impersonating the account manager's email, pulls the PDF from Drive, and sends a short email whose body is also templated from the reference sheet.
The email template is deliberately plain. Two sentences acknowledging the period, one line noting the total and the due date, the invoice attached, and a close. No marketing copy, no upsell, no dashboard link. Clients open and pay plain invoices faster than they open branded HTML invoices because plain invoices read as trustworthy and HTML invoices read as bulk.
After the email is sent the flow updates three things. It sets the status of every timesheet row included in this invoice to billed along with the invoice number so the same hours cannot appear on a future invoice, it writes the send date into the invoice log sheet, and it schedules two follow-up workflows through n8n's Schedule trigger. One checks the invoice log on day fourteen after send and pings the account manager in Slack if the paid date is still empty. The second does the same on day twenty-eight with a stronger prompt to pick up the phone.
Payment reconciliation is the last piece. A separate n8n workflow listens for Stripe payment webhooks, matches amount and client against the invoice log, and writes the paid date automatically. Bank payments still require a human to mark paid once a week, and that is fine. Perfect automation is not worth integration effort for a handful of legacy clients.
What Breaks and How We Handle It
Every automation has failure modes and an honest article names them. Three things have broken in the year we have been running this build for our agency clients. The first is the parser occasionally misclassifying a client code when two clients have similar names. We caught this early and added a confirmation DM for any message where the parser's confidence signal was below a threshold. This adds a small amount of friction but eliminates the class of error where hours are billed to the wrong client.
The second is the Google Docs batch update failing silently when a merge tag is misspelled in the template. A designer once renamed a placeholder without telling anyone. The fix is a pre-send validator node that diffs the expected placeholders against the ones actually present in the document and fails loudly if anything does not match. This runs in about two seconds and has caught three template drift incidents.
The third is the approval Wait node timing out if the founder is on vacation. n8n Wait nodes can hold a workflow open for days, but if the instance restarts the wait state is lost. We now persist the pending approval into a dedicated sheet and reconstruct the Slack message on workflow restart. This is the kind of edge case you only discover after a year, and it is the kind of scar tissue the search results on invoice automation never mention.
When To Build This Yourself and When To Call Us
If your agency is under ten people and every invoice is substantially the same, you can build this yourself in a weekend if you are already comfortable with n8n. The tools are all no-code in the sense that you do not write a backend, but the parser prompt, the Docs template wiring, and the approval resume pattern each have sharp edges that eat time on a first attempt. Budget a week if you are learning n8n alongside the build.
If your agency is larger, or your invoices include retainers mixed with hourly work, or you bill in multiple currencies, or your clients require PO numbers and net-sixty terms, the build gets more complex. The parser needs more training examples. The template needs conditional sections. The approval step needs escalation rules. At that point it is usually cheaper to have someone who has built this five times do it than to spend a month of founder time learning.
This is exactly what WitsCode agency billing automation engagements deliver. We embed for two to three weeks, build the workflow on your n8n instance using your Google Workspace, and leave behind a system your operations lead can edit without calling us. If billing is the bottleneck between doing great client work and getting paid for it on time, that is the problem we want to solve for you.
Get weekly field notes.
Practical writing on shipping products, straight to your inbox. No spam.
Need help with this?
Custom Web Applications
We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.
Talk to usWant to discuss non-tech founders for your business?
Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.