On a schedule
Get last month's client hours for invoicing
On the first of each month your billable hours per client are in your inbox, ready to turn into invoices.
- Runs
- On a schedule
- Apps
- Toggl Track
- AI
- Not needed
- Access
- read
Send this to your assistant
Create a ClickRuntime automation: on the 1st of every month at 8am, email me last month's Toggl Track hours per client, rounded to two decimals.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
Invoicing day is when a freelancer or small agency owner finds out how messy the month was. They open Toggl Track, set the date range to last month, switch the grouping to client, export and copy the numbers into an invoice template. One wrong date range and a client is billed for last month plus three days of the next.
On the first of each month, this requests Toggl's summary report for the previous calendar month, grouped by client, and emails you the totals. The figures are waiting when you sit down to invoice, and the date range is always exactly the month that just ended.
It works best if every project in Toggl is attached to a client. It removes the fiddly report setup that people tend to postpone until a client is already asking for the invoice.
What you get out of it
Invoices start from correct totals
The date range is calculated for you, so the numbers match the calendar month that just closed. That removes the classic error of billing a client for days that belong on next month's invoice.
Money does not wait on a forgotten report
When the totals arrive on the 1st, invoices go out on the 1st or 2nd. Faster invoicing shortens the wait for payment, which matters when cash flow is tight for a small business.
See which clients take the most time
Hours per client in one view shows where the month went. If one account used half your capacity at a low rate, you have evidence for a pricing conversation. That gives you something concrete to bring to the next pricing conversation.
One month, one comparable record
Receiving the same summary monthly lets you spot trends across your inbox, such as a client growing or an account going quiet, without maintaining a spreadsheet of your own. Over a year, twelve emails tell the story of your client base.
No exporting and re-grouping
You skip the clicks of choosing the range, the grouping and the export. That is only a few minutes, but it removes a task people tend to put off until the invoice is overdue.
How it works
What happens, step by step
On the 1st of every month at 8 am, ClickRuntime pulls last month's tracked time from Toggl Track.
It totals the hours for each client.
You get one email with the hours per client, ready to use when you write invoices.
Before it runs live
- Connect Toggl Track
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Toggl Track steps into one automation
Under the hood
The code that runs this automation
from collections import defaultdict
from datetime import date, timedelta
from clickruntime import on_trigger, credentials, http, notify
API = "https://api.track.toggl.com/api/v9/me"
@on_trigger
def run(event):
auth = (credentials.secret("TOGGL_API_TOKEN"), "api_token")
first_this = date.today().replace(day=1)
first_last = (first_this - timedelta(days=1)).replace(day=1)
entries = http.get(f"{API}/time_entries", auth=auth, params={
"start_date": first_last.isoformat(), "end_date": first_this.isoformat()}).json()
projects = {p["id"]: p.get("client_id") for p in http.get(f"{API}/projects", auth=auth).json() or []}
clients = {c["id"]: c["name"] for c in http.get(f"{API}/clients", auth=auth).json() or []}
hours = defaultdict(float)
for e in entries:
if e["duration"] >= 0:
hours[clients.get(projects.get(e.get("project_id")), "No client")] += e["duration"] / 3600
lines = [f"{c}: {h:.2f} h" for c, h in sorted(hours.items(), key=lambda x: -x[1])]
notify.email_me(f"Toggl hours for {first_last:%B %Y}", "\n".join(lines) or "No time tracked.")
return {"clients": len(hours)}FAQ
Common questions
Does it include unbilled or non-billable time?
What happens to time not assigned to a client?
Can the report show earnings as well as hours?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Get your week's hours by client and project
Every Friday afternoon you see where your week went, broken down by client and project in hours.
See how it worksReceive an evening list of what you tracked
Each evening you get today's entries with a total, handy for checking nothing is missing before you log off.
See how it worksGet warned about a timer left on too long
If a timer has been running more than four hours you get one email naming the entry, project and start time.
See how it worksKeep exploring
Set up “Get last month's client hours for invoicing” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.