---
title: timesheets.list | Doing Work API
description: Time entries in a shop between dates (the shop's time zone), or on one job, with minutes by category and by person, and approved minutes. Owner and office 
url: https://doingwork.work/docs/reference/timesheets-list/
---

# timesheets.list

Time entries in a shop between dates (the shop's time zone), or on one job, with minutes by category and by person, and approved minutes. Owner and office see everyone; a field worker sees only their own time. Labor cost shows only for members who may see costs (see_costs). Voided entries are left out unless status is void.

|  |  |
|---|---|
| Who | Agents can call this |
| REST | `GET /v1/timesheets` |
| MCP tool | `timesheets_list` |
| Writes | no |
| Area | [Field work (checklists, forms, time, notes, change orders, subcontractors)](https://doingwork.work/docs/reference/#field-work-checklists-forms-time-notes-change-orders-subcontractors) |

## When to use it

Keep the crew's time: timesheets.clockIn starts a clock on a job (category work) or for drive, shop or break time, and timesheets.clockOut stops it; one clock runs per person per shop (pass stop_running to switch). Forgotten time goes in with timesheets.add (start and end, at most 24 hours per entry); time never overlaps the same person's other time.

## What to tell the owner

Tell them what you found in plain words. Don't read back raw fields.

## Input

| Field | Type | Required |
|---|---|---|
| `shop_id` | string (uuid) | no |
| `job_id` | string (uuid) | no |
| `person_id` | string (uuid) | no |
| `from` | string | no |
| `to` | string | no |
| `status` | string (one of running, pending, approved, rejected, void) | no |
| `category` | string (one of work, drive, shop, break) | no |

## Example

```http
GET https://doingwork.work/v1/timesheets?shop_id=00000000-0000-4000-8000-000000000000&job_id=00000000-0000-4000-8000-000000000000&person_id=00000000-0000-4000-8000-000000000000&from=...&to=...&status=running&category=work
```

## Output

| Field | Type | Always there |
|---|---|---|
| `shop_id` | string (uuid) | yes |
| `time_zone` | string | yes |
| `items` | array | yes |
| `items[].time_entry_id` | string (uuid) | yes |
| `items[].shop_id` | string (uuid) | yes |
| `items[].person_id` | string (uuid) | yes |
| `items[].person_name` | ['string', 'null'] | yes |
| `items[].job_id` | ['string', 'null', ' ', '(', 'u', 'u', 'i', 'd', ')'] | yes |
| `items[].visit_id` | ['string', 'null', ' ', '(', 'u', 'u', 'i', 'd', ')'] | yes |
| `items[].category` | string | yes |
| `items[].started_at` | string (date-time) | yes |
| `items[].ended_at` | ['string', 'null', ' ', '(', 'd', 'a', 't', 'e', '-', 't', 'i', 'm', 'e', ')'] | yes |
| `items[].minutes` | ['integer', 'null'] | yes |
| `items[].source` | string | yes |
| `items[].notes` | ['string', 'null'] | yes |
| `items[].status` | string | yes |
| `items[].cost_rate_minor` | ['integer', 'null'] | yes |
| `items[].labor_cost_minor` | ['integer', 'null'] | yes |
| `items[].decided_by` | ['string', 'null', ' ', '(', 'u', 'u', 'i', 'd', ')'] | yes |
| `items[].decided_at` | ['string', 'null', ' ', '(', 'd', 'a', 't', 'e', '-', 't', 'i', 'm', 'e', ')'] | yes |
| `items[].decision_note` | ['string', 'null'] | yes |
| `items[].entered_by` | string (uuid) | yes |
| `items[].created_at` | string (date-time) | yes |
| `items[].updated_at` | string (date-time) | yes |
| `minutes` | integer | yes |
| `approved_minutes` | integer | yes |
| `pending_minutes` | integer | yes |
| `by_category_minutes` | object | yes |
| `by_person` | array | yes |
| `by_person[].person_id` | string (uuid) | yes |
| `by_person[].person_name` | ['string', 'null'] | yes |
| `by_person[].minutes` | integer | yes |
| `by_person[].approved_minutes` | integer | yes |
| `labor_cost_minor` | ['integer', 'null'] | yes |

```json
{
  "shop_id": "00000000-0000-4000-8000-000000000000",
  "time_zone": "...",
  "items": [
    {
      "time_entry_id": "00000000-0000-4000-8000-000000000000",
      "shop_id": "00000000-0000-4000-8000-000000000000",
      "person_id": "00000000-0000-4000-8000-000000000000",
      "person_name": "...",
      "job_id": "00000000-0000-4000-8000-000000000000",
      "visit_id": "00000000-0000-4000-8000-000000000000",
      "category": "...",
      "started_at": "...",
      "ended_at": "...",
      "minutes": "...",
      "source": "...",
      "notes": "...",
      "status": "...",
      "cost_rate_minor": "...",
      "labor_cost_minor": "...",
      "decided_by": "00000000-0000-4000-8000-000000000000",
      "decided_at": "...",
      "decision_note": "...",
      "entered_by": "00000000-0000-4000-8000-000000000000",
      "created_at": "...",
      "updated_at": "..."
    }
  ],
  "minutes": 1,
  "approved_minutes": 1,
  "pending_minutes": 1,
  "by_category_minutes": {},
  "by_person": [
    {
      "person_id": "00000000-0000-4000-8000-000000000000",
      "person_name": "...",
      "minutes": 1,
      "approved_minutes": 1
    }
  ],
  "labor_cost_minor": "..."
}
```

## Errors

| Code | Status | What to do |
|---|---|---|
| `invalid_input`, `invalid_token`, `rate_limited` |  | Can happen on any call. See [errors](https://doingwork.work/docs/errors/). |
