# List Time Entries — Harvest

> Retrieve a list of time entries from Harvest, with optional filters, automatically following pagination up to 200 entries. Use this to discover time entry IDs for Get Time Entry, Update Time Entry, or Delete Time Entry. For a pure "how…

- Key: `harvest-list-time-entries`
- Type: Action (Read-only)
- Version: 0.0.1
- App: Harvest (`harvest`) — https://pipedream.com/apps/harvest.md
- This page (HTML): https://pipedream.com/apps/harvest/actions/list-time-entries
- Hints: read-only · open-world
- Source: https://github.com/PipedreamHQ/pipedream/blob/master/components/harvest/actions/list-time-entries/list-time-entries.mjs

## Description

Retrieve a list of time entries from Harvest, with optional filters, automatically following pagination up to 200 entries. Use this to discover time entry IDs for **Get Time Entry**, **Update Time Entry**, or **Delete Time Entry**. For a pure "how many entries are there" question, set `countOnly` to skip fetching any entries and just return the true total — safe even on a huge, unfiltered result set that would otherwise exceed the response-size limit. Pass `notes` to filter results to entries whose notes contain that text (client-side, case-insensitive substring) — useful for finding one entry inside a large result set without hitting the output-size limit. Example: call with projectId set to a project's ID and from/to set to a date range to total up hours logged that week. [See the documentation](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#list-all-time-entries).

## Props

| Prop | Type | Required | Description |
|---|---|---|---|
| `accountId` | `string` | Yes | Your Harvest account ID, e.g. 1234567. Run List Account ID Options to find it. |
| `userId` | `string` | No | Free-form user ID, e.g. 1782959. Run List Users first to find valid IDs. |
| `clientId` | `string` | No | Free-form client ID, e.g. 5735776. Run List Clients first to find valid IDs. |
| `projectId` | `string` | No | Free-form project ID, e.g. 14308069. Run Get Projects first to find valid IDs. |
| `taskId` | `string` | No | Free-form task ID, e.g. 1467097. Run List Tasks first to find valid IDs. |
| `isBilled` | `boolean` | No | Only return entries that have or have not been invoiced. |
| `isRunning` | `boolean` | No | Only return running or non-running entries. |
| `updatedSince` | `string` | No | Only return records updated since this UTC datetime, e.g. 2019-06-25T15:30:00Z. |
| `from` | `string` | No | Only return entries with a spent_date on or after this date, format YYYY-MM-DD, e.g. 2026-09-01. |
| `to` | `string` | No | Only return entries with a spent_date on or before this date, format YYYY-MM-DD, e.g. 2026-09-10. |
| `notes` | `string` | No | Only return entries whose notes contain this text (case-insensitive substring match, applied client-side). Use this to find a specific entry inside a large result set instead of paging through everything. |
| `countOnly` | `boolean` | No | Skip fetching entries entirely and just return the true total for the given filters (via Harvest's own count). Use this for "how many" questions — safe on any result size, since it never fetches the entries themselves. |

## Run it

**MCP**

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
import { PipedreamClient } from "@pipedream/sdk"

const pd = new PipedreamClient({
  projectId: process.env.PIPEDREAM_PROJECT_ID!,
  clientId: process.env.PIPEDREAM_CLIENT_ID!,
  clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
  projectEnvironment: "production",
})

const accessToken = await pd.rawAccessToken

const transport = new StreamableHTTPClientTransport(
  new URL("https://remote.mcp.pipedream.net/v3"),
  {
    requestInit: {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "x-pd-project-id": process.env.PIPEDREAM_PROJECT_ID!,
        "x-pd-environment": "production",
        "x-pd-external-user-id": "{external_user_id}", // any stable ID for this user in your system
        "x-pd-app-slug": "harvest",
      },
    },
  },
)

const mcp = new Client({ name: "my-agent", version: "1.0.0" })
await mcp.connect(transport)

const { tools } = await mcp.listTools()

// listTools() hands your model this tool's input schema, so it can
// fill the arguments itself:
const result = await mcp.callTool({
  name: "harvest-list-time-entries",
  arguments: {
    accountId: "Account ID",
    userId: "User ID",
  },
})
```

**TypeScript**

```ts
import { PipedreamClient } from "@pipedream/sdk"

const pd = new PipedreamClient({
  projectId: process.env.PIPEDREAM_PROJECT_ID!,
  clientId: process.env.PIPEDREAM_CLIENT_ID!,
  clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
  projectEnvironment: "production",
})

const result = await pd.actions.run({
  id: "harvest-list-time-entries",
  externalUserId: "{external_user_id}", // any stable ID for this user in your system
  configuredProps: {
    harvest: { authProvisionId: "apn_xxxxxxx" },
    accountId: "Account ID",
    userId: "User ID",
  },
})

console.log(result)
```

**cURL**

```bash
curl -X POST https://api.pipedream.com/v1/connect/{project_id}/actions/run \
  -H "Content-Type: application/json" \
  -H "X-PD-Environment: production" \
  -H "Authorization: Bearer {access_token}" \
  -d '{
    "external_user_id": "{external_user_id}",
    "id": "harvest-list-time-entries",
    "configured_props": {
      "harvest": { "authProvisionId": "apn_xxxxxxx" },
      "accountId": "Account ID",
      "userId": "User ID"
    }
  }'
```

---

- App: https://pipedream.com/apps/harvest.md · All apps: https://pipedream.com/apps
