ClickUp Time Tracking Reports and Timesheets in Google Sheets

ClickUp's own time reports stop where your rate card starts. How to pull raw time entries into Google Sheets and build a timesheet you can bill from.

Title card showing ClickUp time entries becoming a timesheet in Google Sheets on a dark background

ClickUp's native time reports are fine for the questions ClickUp anticipated. Billable hours by person this month, time by List, time in status. The moment you need a rate card applied per client, a utilization percentage against contracted hours, or an invoice line grouped the way your accountant wants it, you are past what the built-in reports do.

Time entries in a spreadsheet solve all of those, because a spreadsheet is where rate cards and utilization targets already live. Getting them there is the part worth doing carefully.

Native time reporting coverage

Tracking itself runs on every plan: a timer on the task, manual entries, a duration and a note per entry. Free Forever caps the Time Tracking ClickApp at 60 uses in total, and those uses do not reset. Above Free you get:

  • Time reporting and Timesheets, which roll entries up by person, by day, and by List. That is the weekly timesheet most teams are after.
  • Billable rates and timesheet approvals, on Business at $12 per user per month billed annually.
  • Dashboard time cards, which chart the same data live, with card data export on Business and above.

All of that reports time as ClickUp understands it. A rate that changes per client, an hours target per person, an invoice cut-off date, a margin per project: none of those are ClickUp fields, so a report that joins to them has to happen elsewhere. The Free plan limits lay out the rest of the ladder.

Time entry contents

A time entry is its own object, separate from the task. Through the API each one carries:

  • id, and wid for the workspace
  • task, with the task's id, custom id, name, and status
  • user, with id, username, email, initials
  • start, end, and duration, all in milliseconds
  • billable, a boolean
  • description, the note the person typed when they logged it
  • tags, the labels on the entry itself
  • source, how it was created
  • at, when the entry was recorded
  • optional task_location, task_tags, and task_url

Two of those matter more than the rest.

duration is in milliseconds, and a negative value means the timer is still running. An entry with a negative duration is somebody's clock ticking right now. Sum a column without filtering those out and your total goes down as the day goes on.

billable is per entry, not per task. The same task can carry billable and non-billable time, which is exactly what you want and exactly what a task-level report cannot show you.

A spreadsheet of 4 ClickUp time entries logged against one task, where the running timer holds a negative duration of minus 1,980,000 milliseconds. SUM over the hours column reads 3.95 and SUMIF against greater than zero reads 4.50, and one of the 4 entries is non-billable

Getting the entries out

3 routes move entries into Sheets. Pick one.

Through the API

The endpoint is GET /team/{team_id}/time_entries. The parameters that matter:

  • start_date and end_date, both Unix milliseconds. Without them you get the last 30 days, authored by the authenticated user only, which is the most common reason a first attempt returns a suspiciously small number of rows.
  • assignee, a user id, or several comma-separated. Pulling other people's entries requires admin or owner access.
  • One of space_id, folder_id, list_id, or task_id to narrow the location. One at a time; they do not combine.
  • include_task_tags and include_location_names, both worth turning on, because otherwise you get ids where you wanted the Space and Folder names and you will be joining them back yourself.

The date boundary is the detail that catches people. Time entries use a midnight UTC boundary. If your team is in UTC+2, the entries logged between midnight and 2am local belong to the previous UTC day, and a "this week" report built on naive local dates will move a few hours across the week boundary every Monday. Decide which convention your report uses and make it explicit in a header cell, because whoever reads the numbers will assume the other one.

Task dates follow a 4AM UTC boundary instead, which is a second convention living in the same spreadsheet the moment you put task rows next to entry rows. Filter each tab on its own boundary rather than on one shared date column. Why ClickUp dates come out wrong in Google Sheets covers the task side, including the 4am timestamps on all-day tasks.

3 time entries logged by a UTC+2 team, where an entry started Tuesday at 01:15 local is stored as 2026-08-10T23:15Z and counts against Monday, because time entries land on a midnight UTC boundary

Through the export

ClickUp's List and Table view export carries time tracked as a task-level total, not as individual entries. That is enough for "how long did this task take" and not enough for a timesheet, because the per-person, per-day, per-note breakdown is exactly what got collapsed.

If you export, set the Time Format to hh:mm rather than the 10h 5m default. 10:05 is a duration Google Sheets can sum; 10h 5m is a string you have to parse.

Through the add-on

ClickUp to Sheets syncs time entries as their own row type on the Pro plan and above, with the task, the person, the date, the duration, and the billable flag already split into columns. That is the shape the rest of this article assumes, because it is the shape you want whichever route you take.

The 3 reports worth building

Assume a TimeEntries tab with columns for Date, Person, Task, List, Hours, Billable, and Description.

A time tracking report built in Google Sheets from synced ClickUp time entries, with total time spent, total billable time and average session duration across the top, and bar charts for weekly hours, time per Space, time per List and the 10 tasks carrying the most time
Time entries synced as their own rows, with the report built on the tab beside them.

Timesheet by person and week

=QUERY(TimeEntries!A:G,
  "select B, sum(E) where A >= date '2026-08-03' and A <= date '2026-08-09'
   group by B order by sum(E) desc label sum(E) 'Hours'", 1)

The value of this over ClickUp's version is the row underneath it, where you divide by contracted hours to get utilization. ClickUp does not know anybody's contracted hours; your spreadsheet does.

Billable value by client

If your client is a Space or a Folder, and you have a rate card on another tab:

=SUMPRODUCT((TimeEntries!$F:$F=TRUE) * (TimeEntries!$D:$D=$A2) * TimeEntries!$E:$E * VLOOKUP($A2, Rates!$A:$B, 2, FALSE))

This is the calculation that pays for the whole exercise. Rates change per client, sometimes per person per client, and no project tool models that well. A lookup table does.

The unbilled backlog

=QUERY(TimeEntries!A:G,
  "select D, sum(E) where F = TRUE and A < date '2026-08-01'
   group by D label sum(E) 'Unbilled hours'", 1)

Billable time older than your last invoice date is money you earned and did not ask for. It is the report nobody builds and everybody should.

Once these rows exist, joining them to each task's time_estimate answers a fourth question: which categories of work run over, and by how much. ClickUp time estimates against actual builds that report on the same tab.

4 things that will bite you

Running timers. Filter out negative durations, or your totals shift under you. =SUMIF(E:E, ">0") rather than =SUM(E:E).

Deleted entries. People delete a mis-started timer. If your sync only ever adds rows, the deleted entry stays in the sheet and you invoice for it. Check that whatever moves the data also removes rows, and if you built it yourself, replace the range rather than appending to it.

Manual entries versus timers. The source field distinguishes them. A workspace with a lot of manually entered round numbers is telling you something about data quality that the total conceals.

Rounding, twice. ClickUp stores milliseconds. If you round to the nearest quarter hour per entry and then sum, you get a different number from summing and then rounding. Pick one, write it in the header, and apply it in exactly one place.

Dashboard card limits

ClickUp Dashboards do time reporting well, and on Business and above you can export a card's data as CSV. 2 things push teams to Sheets anyway.

The first is that a Dashboard card is a view of ClickUp data with ClickUp's vocabulary. Contracted hours, rate cards, invoice dates, and revenue targets are not ClickUp concepts, so any report that joins against them has to happen somewhere else.

The second is that exporting a card is still a manual act on a schedule that depends on a person. A synced tab refreshes itself, and the report on the next tab refreshes with it. ClickUp Dashboards compared with Google Sheets reporting works through which questions belong to which tool.