# GET /api/v2/work-items/{work_item}

Read a work item

- MCP id: work-items.show
- Scope: api:read:project_management
- Permission: project_management::view_backlog
- Rate cost: 1 unit, read bucket.
- Cache-Control: private, no-store

Returns one work item in the detail view, addressed by numeric id or by its issue key: `work-items/41` and `work-items/ACM-123` are the same record.

The strong `ETag` is derived from `version`, so `If-None-Match` answers `304` on an unchanged item and the same value works as `If-Match` on a write. Reading additionally requires `project_management::manage_work_items`. Comments, subtasks, links, attachments, child work items, labels and linked drive documents are reached through `data.links`; comments, subtasks, labels and drive documents can also be expanded inline with include, up to 25 of each.

## Parameters
- work_item (integer or string, path): The WorkItem's numeric id. Or its issue_key, matching `[A-Z][A-Z0-9]*-[0-9]+`.
- view (string, optional): Which field set to render.
- meta (array of string, optional): Optional meta members to compute for this response.
- 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.
- issue_key (string or null ≤ 255, required, server-assigned): Human-readable key, e.g. `ACM-123`, allocated by the server from the project's customer code and a per-customer sequence. It also works in the path: GET `work-items/ACM-123` works. This is one of the two fields `?q=` searches.
- title (string ≤ 255, required): Work item title. The other field `?q=` searches.
- description (html or null, required, detail only): Work item description. HTML from the rich editor, sanitised on read and on write. Mention spans are preserved verbatim, so pass them back unchanged. Detail view only.
- priority (string or null, required): Relative priority. Defaults to normal on create; `null` only on a legacy item that was never prioritised.
- due_date (date (YYYY-MM-DD) or null, required): Due date, a zone-free calendar date. Null when no date was set.
- estimation (integer or null, required): Original estimate, in minutes.
- remaining_estimate (integer or null, required): Remaining estimate, in minutes. Null where none was entered, in which case plnnrly derives one from the estimate and the logged time.
- location_name (string or null ≤ 255, required, detail only): Name of the place the work happens, as picked from the address search in plnnrly. Null when no location was set. Send it together with `location_latitude` and `location_longitude`; `null` all three to clear the location. Detail view only.
- location_address (string or null ≤ 255, required, detail only): Formatted address of the location, when the place has one. Detail view only.
- location_latitude (decimal (2 dp) or null -90 to 90, required, detail only): Latitude of the location in decimal degrees, -90 to 90. Detail view only.
- location_longitude (decimal (2 dp) or null -180 to 180, required, detail only): Longitude of the location in decimal degrees, -180 to 180. Detail view only.
- order (integer, required, server-assigned): Position within the sprint or backlog, and the default sort. Not writable through PATCH: move an item with POST `work-items/{work_item}/actions/move` and `list: backlog`.
- column_order (integer or null, required, server-assigned): Position within the board column. Not writable through PATCH: move a card with `POST work-items/{work_item}/actions/move` and `list: board`.
- version (integer, required): Revision counter, bumped once per write. It is the `ETag`'s revision: send it back as `If-Match` to detect a concurrent edit, which answers `412`.
- 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.
- project_id (integer, required): Project this work item belongs to. It cannot change: the issue key was allocated from the project's customer code.
- task_id (integer or null, required): Kanban task this work item is booked against, when it is booked against one. It must belong to the item's project. A sprint project books the running sprint's hours through it, so an item in that project's running sprint needs one; a simple-mode project does not. Setting it also makes the task's owner the assignee. Follow it to `/api/v2/tasks/{task}`.
- workflow_status_id (integer, required): Current workflow status. Not writable through PATCH: moving between statuses is `POST work-items/{work_item}/actions/transition`, because the move is validated against the project workflow.
- work_type_id (integer, required): Work type of this item.
- sprint_id (integer or null, required): Sprint the item sits in. Null means it is in the backlog.
- parent_id (integer or null, required): Parent work item, for a sub-issue. Null on a top-level item.
- assignee_id (integer or null, required): User the work is assigned to. Null on an unassigned item. On a sprint project, setting it also moves the item to that user's only open task in the same budget, or in the project when the item has no task yet; with several or no candidates the task is left as it is.
- reporter_id (integer, required, server-assigned): User who filed the work item. Always the authenticated user at create time; there is no way to file on somebody else's behalf.
- web_url (string, required): Absolute URL that opens this work item in plnnrly, on the organisation's own hostname. It is a stable link, safe to store: it redirects to the first of the project's backlog, all-work list or board the signed-in user may open, and opens the item there; it lands on the project page when none of them applies. Read-only.
- workflow_status (Ref or WorkflowStatusSummary, required): The workflow status this item currently sits in. Always present.
- parent (Ref or WorkItemSummary or null, required): The parent work item, on a sub-issue.
- assignee (Ref or UserSummary or null, required): The user the work is assigned to. Expanding it additionally requires the users prefix's read grant and a token scope covering it.
- reporter (Ref or UserSummary, required): The user who filed the work item. Expanding it additionally requires the users prefix's read grant and a token scope covering it.
- work_type (Ref or WorkTypeSummary, required): The work type of this item. Expanding it additionally requires the `work_types` prefix's read grant and a token scope covering it.
- sprint (Ref or SprintSummary or null, required): The sprint this item sits in, when it is not in the backlog.
- comments_count (integer ≥ 0, required): Number of comments on this work item.
- subtasks_count (integer ≥ 0, required): Number of checklist subtasks on this work item.
- attachments_count (integer ≥ 0, required): Number of files attached to this work item.
- child_work_items_count (integer ≥ 0, required): Number of child work items (sub-issues).
- labels_count (integer ≥ 0, required): Number of labels on this work item.
- drive_items_count (integer ≥ 0, required): Number of linked drive documents the caller may open. Archived documents are not counted.
- links_count (integer, required): Number of work items linked to this one, in either direction.
- links (WorkItemLinks, required)
  - self (url, required): The canonical URI of this record.
  - comments (url, required): Comments on this work item.
  - subtasks (url, required): Checklist subtasks on this work item.
  - links (url, required): Links between this work item and others, in either direction.
  - attachments (url, required): Files attached to this work item.
  - child_work_items (url, required): Child work items (sub-issues) of this work item.
  - labels (url, optional): Every label on this work item, paginated. Present only while the Sprints feature is enabled, as `GET /labels` is.
  - drive_items (url, required): Every drive document linked to this work item that you may open, paginated.
- labels (array of LabelSummary ≤ 25, optional, only with include): Labels on this work item. `label_ids` takes at most 50 ids and replaces the whole set: a label you leave out is removed. Build it from `links.labels`, which lists every label while the Sprints feature is enabled, not from `include=labels`, which stops at 25. Wrapped in `{ data, meta }`; `meta.truncated` says whether the cap was hit and `meta.count` is the full count.
  - id (integer, required): Unique identifier.
  - name (string ≤ 255, required): Label name as shown on the chip.
  - color (string ≤ 255, required): Six-digit hex colour, e.g. `#ef4444`.
- drive_items (array of DriveItemSummary ≤ 25, optional, only with include): Drive documents linked to this work item that you may open. `drive_item_ids` takes at most 25 ids and replaces the whole set: a document you leave out is unlinked, and so is every linked document you cannot open. Build it from `links.drive_items`, not from `include=drive_items`, which stops at 25. Expanding it additionally requires the `project_drive` prefix's access grant and a token scope covering it. Wrapped in `{ data, meta }`; `meta.truncated` says whether the cap was hit and `meta.count` is the full count.
  - id (integer, required): Unique identifier.
  - title (string ≤ 255, required): Item title.
  - owner_type (string, required): The kind of record `owner` points at; it says which branch of `owner` applies.
  - owner_id (integer, required): The id of the record `owner` points at.
  - owner (Ref, required): The project, customer, organisation or user whose drive this item lives in.
- comments (array of CommentSummary ≤ 25, optional, only with include): Comments on this work item, newest first, capped at 25. Follow `links.comments` for the rest. Wrapped in `{ data, meta }`; `meta.truncated` says whether the cap was hit and `meta.count` is the full count.
  - id (integer, required): Unique identifier.
  - author_type (string, required): The kind of record `author` points at; it says which branch of `author` applies.
  - author_id (integer, required): The id of the record `author` points at.
  - author (Ref or UserSummary, required): Who wrote the comment.
  - created_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): When the comment was posted.
- subtasks (array of SubtaskSummary ≤ 25, optional, only with include): Checklist subtasks on this work item, capped at 25. Follow `links.subtasks` for the rest. Wrapped in `{ data, meta }`; `meta.truncated` says whether the cap was hit and `meta.count` is the full count.
  - id (integer, required): Unique identifier.
  - title (string ≤ 255, required): Subtask title.
  - is_resolved (boolean, required): Whether the subtask is ticked off.

## 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/work-items/1' \
  --data-urlencode 'include=labels,comments' \
  -H 'Authorization: Bearer <token>' \
  -H 'Accept: application/json'
```
