
## List entries across the whole Bitrix24 account

`GET /v1/task-time`

Returns time-tracking entries from all tasks in the Bitrix24 account in a single request, with filtering by employee, period and task. Use it when the list of tasks is not known in advance — for example, for an employee's monthly time report.

## Parameters

| Parameter | Type | Default | Description |
|----------|-----|-----------|---------|
| `userId` (query) | number | — | Employee identifier. List: `GET /v1/users`. If omitted, the response includes entries for all employees the key owner can access |
| `from` (query) | string | — | Lower bound of the period, inclusive, by the `createdDate` field. Accepts ISO 8601 `2026-05-01T00:00:00+00:00` and a plain date `2026-05-01` |
| `to` (query) | string | — | Upper bound of the period, inclusive, by the `createdDate` field. Same format as `from`. A plain date covers the whole day |
| `taskId` (query) | number | — | Narrow the result set to a single task, on top of `userId`, `from` and `to`. Identifier: `GET /v1/tasks` |
| `limit` (query) | number | `50` | Page size, from 1 to 500. A value above 500 is clamped to 500 |
| `offset` (query) | number | `0` | Offset within the result set. Must be a multiple of `limit` |

**Pagination.** A single call returns up to 500 entries. With a `limit` above 50, Vibecode assembles the window server-side and returns it in full. The `offset` value must be a multiple of `limit` — `0`, `limit`, `2 × limit`, and so on, otherwise `400 INVALID_OFFSET` is returned. `meta.hasMore` indicates whether more entries exist beyond the window.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/task-time?userId=1&from=2026-05-01&to=2026-05-31" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/task-time?userId=1&from=2026-05-01&to=2026-05-31" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
const url = 'https://vibecode.bitrix24.com/v1/task-time?userId=1&from=2026-05-01&to=2026-05-31'

const res = await fetch(url, {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data, meta } = await res.json()
const totalSeconds = data.reduce((sum, r) => sum + Number(r.seconds), 0)
console.log(`For the period: ${totalSeconds / 3600} h, ${meta.total} entries`)
```

### JavaScript — OAuth application

```javascript
const url = 'https://vibecode.bitrix24.com/v1/task-time?userId=1&from=2026-05-01&to=2026-05-31'

const res = await fetch(url, {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { success, data, meta } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of time-tracking entries |
| `data[].id` | string | Entry identifier |
| `data[].taskId` | string | Parent task identifier. Card: `GET /v1/tasks/:id` |
| `data[].userId` | string | Entry author. Profile: `GET /v1/users/:userId` |
| `data[].seconds` | string | Duration in seconds |
| `data[].minutes` | string | Duration in minutes, derived from `seconds` |
| `data[].commentText` | string | Comment for the entry. An empty comment is returned as `""` |
| `data[].source` | string | Source: `2` — REST API |
| `data[].createdDate` | datetime | When the entry was created |
| `data[].dateStart` | datetime | Start of the tracked interval, filled automatically |
| `data[].dateStop` | datetime | End of the tracked interval, filled automatically |
| `meta.total` | number | Total number of entries matching the filter |
| `meta.limit` | number | Applied page size |
| `meta.offset` | number | Applied offset |
| `meta.hasMore` | boolean | Whether there are more entries beyond the current window |

## Response example

```json
{
  "success": true,
  "data": [
    {
      "id": "161",
      "taskId": "3881",
      "userId": "1",
      "commentText": "Code review",
      "seconds": "900",
      "minutes": "15",
      "source": "2",
      "createdDate": "2026-05-13T16:15:41+00:00",
      "dateStart": "2026-05-13T17:15:41+00:00",
      "dateStop": "2026-05-13T17:15:41+00:00"
    },
    {
      "id": "159",
      "taskId": "3867",
      "userId": "1",
      "commentText": "Build check",
      "seconds": "600",
      "minutes": "10",
      "source": "2",
      "createdDate": "2026-05-06T10:46:12+00:00",
      "dateStart": "2026-05-06T11:46:12+00:00",
      "dateStop": "2026-05-06T11:46:12+00:00"
    },
    {
      "id": "157",
      "taskId": "289",
      "userId": "1",
      "commentText": "Draft preparation",
      "seconds": "1800",
      "minutes": "30",
      "source": "2",
      "createdDate": "2026-05-06T10:45:47+00:00",
      "dateStart": "2026-05-06T11:45:47+00:00",
      "dateStop": "2026-05-06T11:45:47+00:00"
    }
  ],
  "meta": {
    "total": 3,
    "limit": 50,
    "offset": 0,
    "hasMore": false
  }
}
```

## Error response example

400 — `userId` is not a positive integer:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_USER_ID",
    "message": "userId must be a positive integer"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_USER_ID` | `userId` is not a positive integer |
| 400 | `INVALID_TASK_ID` | `taskId` is not a positive integer |
| 400 | `INVALID_OFFSET` | `offset` is not a multiple of `limit` — pagination requires the values `0`, `limit`, `2 × limit`, and so on |
| 403 | `SCOPE_DENIED` | The API key lacks the `task` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**Sorted newest to oldest.** The most recently added entries are returned first. `limit` and `offset` work on top of this sort.

**A malformed date raises no error.** A `from` or `to` value that cannot be parsed as a date yields an empty result set and status `200`. Validate the format on your side.

**An offset past the end of the result set.** A request whose `offset` exceeds the number of entries returns an empty array, and `meta.total` in that response echoes the `offset`. Detect the end of the listing by `meta.hasMore` being `false`, not by comparing `offset` with `meta.total`.

## See also

- [List entries of a task](./list.md)
- [Add an entry](./create.md)
- [Task time tracking](/docs/entities/tasks/time)
- [Tasks](/docs/entities/tasks)
- [Employees](/docs/entities/users)
- [Limits and optimization](/docs/optimization)
