# Time

A worklog: minutes of work booked by one employee against one project on one calendar day, optionally attached to a task and a work item. Billability is inferred from the task, and overriding the inference needs a `billable_change_reason`. An entry that exceeds its budget, or whose billability was overridden, enters a reviewer's queue until a reviewer settles it; while it sits there, and forever after it has been invoiced, it is locked against changes.

## Used by
- GET /api/v2/worklogs: List worklogs (TimeList)
- POST /api/v2/worklogs: Log time (Time)
- GET /api/v2/worklogs/{worklog}: Read a worklog (Time)
- PATCH /api/v2/worklogs/{worklog}: Correct a worklog (Time)

## Time fields
- id (integer, required): Unique identifier.
- date (date (YYYY-MM-DD), required): The calendar day the work happened.
- minutes (integer, required): Duration in minutes, between 1 and 1440.
- description (string ≤ 255, required): What the employee worked on.
- project_id (integer or null, required): Project the hours are booked against; `null` once that project is deleted.
- project (Ref or ProjectSummary or null, required): The project the hours are booked against, always expanded. Its `customer_id` is the customer to fetch with `GET /api/v2/customers/{customer}`; the customer itself is not nested.
- budget_id (integer or null, required, server-assigned): Budget the hours are invoiced against. Derived from the task, never accepted on a write; `null` when no task is set or the budget is deleted.
- budget (Ref or BudgetSummary or null, required): The budget the hours are invoiced against. Expanding it with `?include=budget` additionally requires the `budgets::read` permission and a token scope covering the budgets prefix.
- task_id (integer or null, required): Task the hours are booked on; `null` when the entry is not attached to one, or once that task is deleted.
- task (Ref or TaskSummary or null, required): The task the hours are booked on. Expanding it with `?include=task` additionally requires the `kanban::manage_self` permission and a token scope covering the kanban prefix, and is limited to the tasks you can see on the tasks collection.
- work_item_id (integer or null, required): Work item the hours are attached to; `null` when the entry is not attached to one, or once that work item is deleted.
- work_item (Ref or WorkItemSummary or null, required): The work item the hours are attached to, always expanded.
- user_id (integer or null, required, server-assigned): Employee the hours belong to. Assigned on create (from the authenticated user, or from `on_behalf_of_user_id`) and never writable afterwards; reassigning a worklog is a DELETE plus a POST.
- user (Ref or UserSummary or null, required): The employee the hours belong to. Expanding it with `?include=user` additionally requires the `users::read` permission and a token scope covering the users prefix.
- is_not_billable (boolean, required): Whether these hours are excluded from invoicing. Inferred from the task's `is_billable` flag (`false` without a task) on create and again whenever `task_id` is sent. Sending a value that differs from the inferred or current one requires `billable_change_reason` and puts the entry in a reviewer's queue; without it the write is a `422` on `/billable_change_reason`.
- is_overtime (boolean, required): Whether the hours count as overtime. Sending it without the `times::write_overtime` permission leaves it `false` and adds an `input_ignored` warning rather than failing the write.
- exceeded_budget (boolean, required): Whether the entry was booked knowing it exceeds its budget. Set on create only, and `true` whenever a `reason` is sent; setting it puts the entry in a reviewer's queue.
- reason (string or null, required, detail only, multiline): Why the budget overrun was accepted. Sending it on create marks the entry as exceeding its budget. Once a reviewer has settled the entry it can no longer be changed: a PATCH that does answers `409` `reason_reviewed`.
- billable_change_reason (string or null, required, detail only, multiline): Why the inferred billability was overridden. Required whenever `is_not_billable` is sent with a value that differs from the inferred or current one, on create and on PATCH alike; the override puts the entry in a reviewer's queue, reopening one a reviewer had already settled.
- reviewed_by (integer or null, required, server-assigned): The reviewer who settled the entry, once one has. Set by the review queue in plnnrly; this API exposes no way to write it.
- invoice_id (integer or null, required, server-assigned): The invoice these hours were billed on, once they have been. While it is set, the entry is locked: a write answers `409` with `conflict.reason` `locked_by_invoice`.
- sales_invoice_row_id (integer or null, required, server-assigned): The sales-invoice line these hours were billed on, once they have been. Set by the invoicing flow.
- 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 (TimeLinks, required)
  - self (url, required): The canonical URI of this record.

Only on `?view=detail`: reason, billable_change_reason

## Variants

### TimeList

What a collection returns, and what `?view=summary` returns on a single record.

23 fields.
Omits: reason, billable_change_reason

### TimeSummary

The embedded form: what you get when another resource carries this one and you did not `include` it.

3 fields.
Omits: description, project_id, project, budget_id, budget, task_id, task, work_item_id, work_item, user_id, user, is_not_billable, is_overtime, exceeded_budget, reason, billable_change_reason, reviewed_by, invoice_id, sales_invoice_row_id, created_at, updated_at, links

### TimeLinks

The `links` object on this resource.

Keys: self

## Example
```json
{
  "id": 1,
  "date": "2026-09-10",
  "minutes": 150,
  "description": "Reviewed the invoice export and fixed the rounding",
  "project_id": 12,
  "project": null,
  "budget_id": 1,
  "budget": null,
  "task_id": 88,
  "task": null,
  "work_item_id": 41,
  "work_item": null,
  "user_id": 1,
  "user": null,
  "is_not_billable": false,
  "is_overtime": false,
  "exceeded_budget": false,
  "reason": "…",
  "billable_change_reason": "…",
  "reviewed_by": 1,
  "invoice_id": 1,
  "sales_invoice_row_id": 1,
  "created_at": "2026-03-04T09:15:00Z",
  "updated_at": "2026-03-04T09:15:00Z",
  "links": {
    "self": "https://<your-url>/api/v2/work-items/1"
  }
}
```
