# GET /api/v2/timers

List running timers

- MCP id: timers.index
- Scope: api:read:hours
- Permission: hours::read
- Rate cost: 1 unit, read bucket. `view=detail` makes it 3. Adds: each include +1.
- Cache-Control: private, no-store

Returns the running timers, newest first by `created_at`.

A caller sees only their own rows unless they hold `times::update_others`, and that narrowing is applied before any client filter, before pagination and before the count. `meta.page.total` is always present, so `with_total` is not an accepted parameter. Neither is `q` (a timer has no text to search), nor `meta`, `trashed` or `force`; sending any of them is a `400`. To find the timer on one record, send the type and id together: `filter[timeable_type]=work_item&filter[timeable_id]=41`; a lone half is a `400`. A timer on a record type this API does not publish (an Outlook calendar event, which the agenda really does time) is returned with `timeable_type` set to `outlook_event` and `timeable` as the bare `{"id": N}` reference form, which `?include=timeable` cannot expand.

## Parameters
- view (string, optional): Which field set to render.
- per_page (integer 1 to 100, optional): Rows per page. At most 25 when `include` names a to-many relation; a larger value is 400 invalid-query-parameter.
- cursor (string, optional): Opaque keyset cursor from a previous page's links.next. Never construct one by hand.
- page (integer 1 to 1000, optional): Opt in to page-number paging: 1-based, at most 1000. Omit it, the default, to page by opaque cursor, which is what links.next hands you. Cannot be combined with cursor. Published only on collections that count their rows on every request.
- filter[created_at] (timestamp (YYYY-MM-DDThh:mm:ssZ), optional): Creation timestamp. Pair with `sort=id` for a stable full export. Operators: = gte lt.
- filter[started_at] (timestamp (YYYY-MM-DDThh:mm:ssZ), optional): When the stopwatch was started. Operators: = gte lte.
- filter[timeable_id] (integer, optional): Id of the timed record. Send together with `timeable_type`. Operators: = in.
- filter[timeable_type] (string, optional): Type of the timed record. Send together with `timeable_id`.
- filter[updated_at] (timestamp (YYYY-MM-DDThh:mm:ssZ), optional): Last-write timestamp. Use for incremental sync. Operators: = gte lt.
- filter[user_id] (integer, optional): Whose timers to return. Accepts the literal `me`, and defaults to the authenticated user. Naming another employee requires the `times::update_others` permission. Operators: = in.
- sort (string, optional): Up to three keys, comma-separated, each optionally prefixed with `-` for descending.
- include (string, optional): Comma-separated names to inline, at most five.
- X-Request-Id (header, optional): A correlation id of your own. It is recorded in our logs next to the server's request id but never returned: the response header always carries the server's id. A value that does not match the pattern is discarded silently, never rejected.
- If-None-Match (header, optional): The ETag a read is conditional on. A match is answered 304 with no body.

## Response 200
- id (integer, required): Unique identifier.
- user_id (integer, required, server-assigned): Employee this timer belongs to. Always the authenticated user; a timer cannot be started for someone else.
- user (Ref or UserSummary, required): The employee this timer belongs to. Expanding it with `?include=user` additionally requires the `users::read` permission and a token scope covering the users prefix.
- timeable_type (string, required): The kind of record `timeable` points at; it says which branch of `timeable` applies.
- timeable_id (integer, required): The id of the record `timeable` points at.
- timeable (Ref or WorkItemSummary or EventSummary, required): The record being timed. Expanding it with `?include=timeable` additionally requires the read permission and token scope of the target's own prefix, per branch: `project_management` for a work item, events for a planning event.
- started_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): When the stopwatch was started. Elapsed time is this value against the client's own clock; the API publishes no elapsed counter.
- created_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Creation timestamp.
- updated_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Last-write timestamp; use for incremental sync.
- links (TimerLinks, required)
  - self (url, required): The canonical URI of this record.

## Errors
- 403 forbidden-by-policy | insufficient-permission | insufficient-token-scope: Forbidden.
- 304 : Not modified.
- 400 idempotency-key-required | invalid-cursor | invalid-query-parameter | malformed-request | unsupported-parameter: Bad request.
- 401 token-expired | unauthenticated: Unauthenticated.
- 404 endpoint-not-found | resource-not-found: Not found.
- 406 not-acceptable: Not acceptable.
- 429 rate-limit-exceeded: Too many requests.
- 500 internal-error: Server error.
- 503 tenant-unavailable: Service unavailable.

## Example
```bash
curl -G \
  'https://<your-url>/api/v2/timers' \
  --data-urlencode 'filter[user_id]=me' \
  --data-urlencode 'include=timeable' \
  -H 'Authorization: Bearer <token>' \
  -H 'Accept: application/json'
```
