# Views and includes

Choose a field set with view, inline related records and on-demand fields with include, and read meta.actions and warnings.

Two query parameters decide how much of each record you get back. Neither of them lists individual fields.

| Parameter | What it controls                                                       | Default                                                                                 |
| --------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `view`    | Which of the resource's two field sets you get: `summary` or `detail`. | `summary` on a collection; `detail` on a single read and on the record a write returns. |
| `include` | Which related records and on-demand fields are filled in.              | Nothing extra.                                                                          |

Paths are relative to `https://<your-url>/api/v2`, where `<your-url>` is the address you sign in to plnnrly on, such as `acme.plnnrly.com`, or your organisation's own domain.

## There is no `fields` parameter

You cannot pick single fields. `?fields=…` is `400` [unsupported-parameter](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#unsupported-parameter), and `errors[0].detail` points you to `view`. Use `view` for the field set and `include` for the extras below.

## Summary and detail

Each resource has a summary and a detail field set. On many resources they are the same. Where they differ, the detail set adds the larger fields, such as:

- a work item's `description` and its location fields (`location_name`, `location_address`, `location_latitude`, `location_longitude`)
- a worklog's `reason` and `billable_change_reason`
- a Drive document's `content`
- a user's `working_hours` and `work_locations`

The reference marks which fields are detail-only. In the summary view those fields are absent, not `null`.

```bash
curl -G "https://<your-url>/api/v2/work-items" \
  -H "Authorization: Bearer <token>" \
  --data-urlencode "view=detail"
```

`view=detail` on a collection costs 3 rate units in place of 1, or 5 together with `with_total=1`. On a single read and on a write it costs nothing extra. See [Rate limits](https://developers.plnnrly.com/en/docs/api/v2/guides/rate-limits/).

## Include

`include` takes up to five names, separated by commas. Each name is a related record or an on-demand field of the resource you are reading:

```bash
curl -G "https://<your-url>/api/v2/work-items" \
  -H "Authorization: Bearer <token>" \
  --data-urlencode "include=sprint,labels"
```

One row of the answer:

```jsonc
{
  "id": 812,
  "issue_key": "ACM-12",
  "title": "Export timesheets as CSV",
  "sprint_id": 31,
  "sprint": { "id": 31, "name": "Sprint 14", "is_active": true },
  "labels": {
    "data": [
      { "id": 5, "name": "Backend", "color": "#ef4444" }
    ],
    "meta": { "count": 1, "truncated": false }
  }
  // 30 more fields: priority, due_date, estimation, remaining_estimate, order, column_order, version, created_at, updated_at, project_id, task_id, workflow_status_id, work_type_id, parent_id, assignee_id, reporter_id, web_url, workflow_status, parent, assignee, reporter, work_type, comments_count, subtasks_count, attachments_count, child_work_items_count, labels_count, drive_items_count, links_count, links
}
```

The rules:

- Each name is a single relation or field. A dotted path such as `sprint.project` is `400` [invalid-query-parameter](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#invalid-query-parameter) with code `depth_exceeded`. Read the next record with its own request.
- A sixth name is code `count_exceeded`.
- An unknown name is code `unknown_include_path`, and `errors[].detail` lists the names this resource accepts.
- `include` is documented as a parameter on collection reads.

Each name costs extra rate units: 1 for a single related record or a field, 3 for a relation that holds several records. `include=sprint,labels` costs 1 + 1 + 3 = 5 units. See [Rate limits](https://developers.plnnrly.com/en/docs/api/v2/guides/rate-limits/).

The operation page lists every name it accepts, what it returns, and any extra grant it needs. All limits are listed together in [Limits at a glance](https://developers.plnnrly.com/en/docs/api/v2/guides/limits/).

### One record or several

A relation to **one** record, such as `sprint`, is a bare `{"id": 31}` until you include it. Included, it becomes a short summary of that record. It is `null` when nothing is linked.

A relation to **several** records, such as `labels`, is absent until you include it. Included, it is always wrapped as `{ "data": [...], "meta": {...} }`:

- `meta.truncated` is always present. It is `true` when there were more rows than the cap.
- `meta.count` is the full number of related records, on relations that count them.

With such a relation in `include`, `per_page` goes up to 25 instead of 100. A larger value is `400` with code `out_of_range`.

### On-demand fields

Some fields are left out unless you name them in `include`, because they cost extra work to produce:

| Resource                           | Field            | What it gives you                                                                                                                                                         |
| ---------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Files on a work item or Drive item | `url`            | A download URL, which needs your token. This is the only way to get one. See [Files: upload and download](https://developers.plnnrly.com/en/docs/api/v2/guides/uploads/). |
| Files on a work item or Drive item | `url_expires_at` | When `url` stops working. Always `null` today: the URL does not expire.                                                                                                   |
| Drive documents                    | `content_html`   | The document as sanitised HTML, with the colours, highlights and @mentions that Markdown cannot hold.                                                                     |
| Projects                           | `logged_minutes` | The minutes logged on the project that you may see.                                                                                                                       |

### Includes that need their own grant

Some includes read another area of plnnrly, and need that area's permission and token scope on top of the operation's own. `include=assignee` on work items reads users, for example.

Without that grant, a related record in `include` is `400` with code `unknown_include_path`, and the `detail` says it is not available to you. It is not a `403`. An on-demand field behaves differently: `include=logged_minutes` without access to time entries returns `logged_minutes: null`.

### Names you cannot include

- **A relation that is always filled in.** A work item's `workflow_status` and a worklog's `project` come with every row. Naming one is `400` with code `unknown_include_path`, telling you to remove it.
- **A relation with no summary form.** A Drive item's `content_record` is always a bare reference. Naming it is `400` with code `unknown_include_path`; read the record by its `content_record_id`.
- **Anything, on a resource with nothing to include.** `include` there is `400` [unsupported-parameter](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#unsupported-parameter).

A relation that is always filled in can still come back as a bare `{"id": …}`, when it points at a record you may not read.

### Truncation

A relation that holds several records returns at most 25 of them, or up to 50 for `tags`. When there are more, three things happen:

1. The relation's `meta.truncated` is `true`.
2. `meta.warnings` on the response gets an entry with code `include_truncated`. The status code stays `200`, and the rest of `data` is unchanged.
3. The row has a link of the same name in `links`, such as `links.comments` or `links.labels` on a work item. Follow it to page through the full list. Without that link, the warning's `detail` says that only the first 25 are listed.

```jsonc
{
  "data": [
    {
      "id": 812,
      "comments": {
        "data": [
          // 25 comments, each with id, author_type, author_id, author and created_at
        ],
        "meta": { "truncated": true }
      },
      "links": {
        "self": "https://<your-url>/api/v2/work-items/812",
        "comments": "https://<your-url>/api/v2/work-items/812/comments"
        // 6 more links: subtasks, links, attachments, child_work_items, labels, drive_items
      }
      // 33 more fields: issue_key, title, priority, due_date, estimation, remaining_estimate, order, column_order, version, created_at, updated_at, project_id, task_id, workflow_status_id, work_type_id, sprint_id, parent_id, assignee_id, reporter_id, web_url, workflow_status, parent, assignee, reporter, work_type, sprint, comments_count, subtasks_count, attachments_count, child_work_items_count, labels_count, drive_items_count, links_count
    }
  ],
  "meta": {
    "page": {
      // 4 page fields: per_page, next_cursor, prev_cursor, total
    },
    "warnings": [
      {
        "code": "include_truncated",
        "detail": "The `comments` include returned more than 25 rows; follow links.comments for the rest.",
        "parameter": "include"
      }
    ]
  },
  "links": {
    // 3 links: self, next, prev
  }
}
```

Never treat a truncated relation as the whole set. Check `meta.truncated`, or the `include_truncated` warning.

Every relation that can hold more records than its include returns has such a link, with one exception: a work item has `links.labels` only while your organisation has the Sprints feature, because `GET /labels` needs it too. `tags` needs no link: a project, a customer and a Drive item take at most 50 tags each, and `include=tags` returns up to 50, so it always holds the whole set.

### Changing a set you read through include

Some sets are written as a list of ids, such as `label_ids` on a work item. The list replaces the whole set: an id you leave out is removed. Before you add or remove one entry, read the full set from the row's link, such as `links.labels`, not from a truncated include. Then send the full list with your change.

Each list takes a limited number of ids, stated on the field in the reference. plnnrly links any number of labels and documents to a work item, so those sets can grow past that number there. Such a set cannot be replaced through the API: change it in plnnrly.

## Actions you can call now

On a single-record read, `meta=actions` adds the actions you may call on that record right now:

```bash
curl "https://<your-url>/api/v2/work-items/ACM-12?meta=actions" \
  -H "Authorization: Bearer <token>"
```

```jsonc
{
  "data": {
    // 40 fields in the detail view: id, issue_key, title, description, priority, due_date, estimation, remaining_estimate, location_name, location_address, location_latitude, location_longitude, order, column_order, version, created_at, updated_at, project_id, task_id, workflow_status_id, work_type_id, sprint_id, parent_id, assignee_id, reporter_id, web_url, workflow_status, parent, assignee, reporter, work_type, sprint, comments_count, subtasks_count, attachments_count, child_work_items_count, labels_count, drive_items_count, links_count, links
  },
  "meta": {
    "actions": ["move", "transition"]
  }
}
```

The list takes your token, your permissions and the record's current state into account. When no action applies, for example with a read-only token, `meta.actions` is left out.

`meta=actions` works on single-record reads of resources that have actions, such as work items and sprints. On a collection or a write it is `400` [unsupported-parameter](https://developers.plnnrly.com/en/docs/api/v2/guides/errors/#unsupported-parameter). See [Actions and state changes](https://developers.plnnrly.com/en/docs/api/v2/guides/actions/).

## Warnings

`meta.warnings` is a list of notes about your request. A warning never changes the status code and never changes `data`. It appears only when there is something to say.

| Field         | Meaning                                                                                        |
| ------------- | ---------------------------------------------------------------------------------------------- |
| `code`        | What happened. Switch on this, never on `detail`.                                              |
| `detail`      | An explanation in English.                                                                     |
| `pointer`     | The field in your request body the warning is about, as a JSON pointer such as `/is_overtime`. |
| `parameter`   | The query parameter the warning is about, such as `include`.                                   |
| `sunset`      | For a deprecation: the date it stops working.                                                  |
| `replacement` | For a deprecation: what to use instead.                                                        |

The codes:

| Code                                                              | Meaning                                                                                                                                                      |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `include_truncated`                                               | An included relation hit its cap. See [Truncation](https://developers.plnnrly.com/en/docs/api/v2/guides/views-and-includes/#truncation).                     |
| `input_ignored`                                                   | A field in your write was dropped because your permissions do not cover it. The rest of the write was applied. `pointer` names the field.                    |
| `already_in_target_state`                                         | A restore found the record already restored, so nothing changed.                                                                                             |
| `signed_url_unavailable`                                          | A file's download `url` could not be made, so it is `null`. See [Files: upload and download](https://developers.plnnrly.com/en/docs/api/v2/guides/uploads/). |
| `deprecated_field`, `deprecated_parameter`, `deprecated_endpoint` | You used something that is deprecated. See [Headers and versioning](https://developers.plnnrly.com/en/docs/api/v2/guides/headers-and-versioning/).           |

New codes can be added. Treat a code you do not know as a note to log, never as an error. Each operation page lists the codes it can return.

After every write, check `meta.warnings` for `input_ignored`. Without that check, a dropped field goes unnoticed.

## Related

- [Pagination](https://developers.plnnrly.com/en/docs/api/v2/guides/pagination/): page through the full list a truncated relation links to.
- [Data formats](https://developers.plnnrly.com/en/docs/api/v2/guides/data-formats/): what absent, `null` and `[]` mean.
- [Rate limits](https://developers.plnnrly.com/en/docs/api/v2/guides/rate-limits/): what `view` and `include` cost.
