# Views

A view is a saved way to look at a team's or a project's tickets: filters, grouping, order and layout. Each view belongs to one team or one project, and anyone who sees that team or project can read it. Changes to a view apply for everyone.

## The View object

A saved way to look at a team's or a project's tickets: filters, grouping, order and layout.

### Attributes

- `id` (string, required): Unique ID of the view.
- `slug` (string, required): Made from the view's name and unique within its team or project, such as active.
- `name` (string, required): The view's name, such as Active.
- `team` (nullable object, required): The team the view belongs to, or null for a project view.
  - `id` (string, required): Unique ID of the team.
  - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
  - `name` (string, required): The team's display name.
- `project` (nullable object, required): The project the view belongs to, or null for a team view.
  - `id` (string, required): Unique ID of the project.
  - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
  - `name` (string, required): The project's display name.
- `filters` (object, required): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `milestone`, `team`, `none`, required): How the view groups tickets.
- `orderBy` (string, one of: `manual`, `created`, `updated`, required): How the view orders tickets: manual follows the order people set by hand, created puts the newest first and updated the most recently changed.
- `layout` (string, one of: `list`, `board`, required): Whether the view shows a list or a board.
- `isDefault` (boolean, required): Whether the team's or project's Tickets page opens this view.
- `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
- `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.

### Example

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z"
}
```

## List a team's views

`GET /v1/workspaces/{slug}/teams/{team}/views`

Returns the team's saved views. Every team starts with All tickets, Active and Backlog.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `team` (string, in path, required): The team's key, such as WEB.

### Returns

Returns an object with these fields. The status is 200.

- `views` (array of objects, required): The views, the default first, then in the order they were saved. See [the View object](https://docs.qa.clankership.net/api/views/object.md).
  - `id` (string, required): Unique ID of the view.
  - `slug` (string, required): Made from the view's name and unique within its team or project, such as active.
  - `name` (string, required): The view's name, such as Active.
  - `team` (nullable object, required): The team the view belongs to, or null for a project view.
    - `id` (string, required): Unique ID of the team.
    - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
    - `name` (string, required): The team's display name.
  - `project` (nullable object, required): The project the view belongs to, or null for a team view.
    - `id` (string, required): Unique ID of the project.
    - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
    - `name` (string, required): The project's display name.
  - `filters` (object, required): Which tickets a view shows. Filters combine with and; the values within one filter with or.
    - `statuses` (array of strings): Only tickets with these statuses, by name.
    - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
    - `tags` (array of strings): Only tickets with any of these tags, by name.
    - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
    - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
    - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
    - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
  - `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `milestone`, `team`, `none`, required): How the view groups tickets.
  - `orderBy` (string, one of: `manual`, `created`, `updated`, required): How the view orders tickets: manual follows the order people set by hand, created puts the newest first and updated the most recently changed.
  - `layout` (string, one of: `list`, `board`, required): Whether the view shows a list or a board.
  - `isDefault` (boolean, required): Whether the team's or project's Tickets page opens this view.
  - `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
  - `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug}/teams/{team}/views \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "views": [
    {
      "id": "Vw4AcT8nRk2P",
      "slug": "active",
      "name": "Active",
      "team": {
        "id": "Tm6PzN3kWq1J",
        "key": "WEB",
        "name": "Web"
      },
      "project": null,
      "filters": {
        "categories": [
          "unstarted",
          "started"
        ]
      },
      "groupBy": "status",
      "orderBy": "manual",
      "layout": "board",
      "isDefault": false,
      "createdAt": "2026-10-01T16:20:00.000Z",
      "updatedAt": "2026-10-14T09:05:12.000Z"
    }
  ]
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Create a team view

`POST /v1/workspaces/{slug}/teams/{team}/views`

Saves a view of the team's tickets, with a slug made from its name. Team views group by status, category, owner, tag, project or none. Members of the team and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `team` (string, in path, required): The team's key, such as WEB.
- `name` (string, required): The view's name, up to 60 characters, unique within its team or project.
- `filters` (object): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `none`): How the view groups tickets. Defaults to status.
- `orderBy` (string, one of: `manual`, `created`, `updated`): `manual` follows the order people set by hand, `created` puts the newest first and `updated` the most recently changed. Defaults to manual.
- `layout` (string, one of: `list`, `board`): A list or a board. Defaults to list.

### Returns

Returns the [View](https://docs.qa.clankership.net/api/views/object.md) object. The status is 201.

### Request

```bash
curl -X POST https://api.qa.clankership.net/v1/workspaces/{slug}/teams/{team}/views \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search work",
    "filters": {
      "categories": [
        "unstarted",
        "started"
      ],
      "tags": [
        "feature"
      ]
    },
    "groupBy": "owner",
    "layout": "board"
  }'
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Get a team view

`GET /v1/workspaces/{slug}/teams/{team}/views/{view}`

Returns the view with the tickets it shows, in its order, and the team's statuses for a status grouping's columns.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `team` (string, in path, required): The team's key, such as WEB.
- `view` (string, in path, required): The view's slug, such as active.

### Returns

Returns an object with these fields. The status is 200. A view with the tickets it shows.

- `id` (string, required): Unique ID of the view.
- `slug` (string, required): Made from the view's name and unique within its team or project, such as active.
- `name` (string, required): The view's name, such as Active.
- `team` (nullable object, required): The team the view belongs to, or null for a project view.
  - `id` (string, required): Unique ID of the team.
  - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
  - `name` (string, required): The team's display name.
- `project` (nullable object, required): The project the view belongs to, or null for a team view.
  - `id` (string, required): Unique ID of the project.
  - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
  - `name` (string, required): The project's display name.
- `filters` (object, required): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `milestone`, `team`, `none`, required): How the view groups tickets.
- `orderBy` (string, one of: `manual`, `created`, `updated`, required): How the view orders tickets: manual follows the order people set by hand, created puts the newest first and updated the most recently changed.
- `layout` (string, one of: `list`, `board`, required): Whether the view shows a list or a board.
- `isDefault` (boolean, required): Whether the team's or project's Tickets page opens this view.
- `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
- `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.
- `tickets` (array of objects, required): The tickets the view shows, in its order.
  - `id` (string, required): Unique ID of the ticket.
  - `identifier` (string, required): The team key and number, such as WEB-31. Paths take this ID.
  - `number` (number, required): The ticket's number within its team.
  - `team` (object, required): A team as tickets and projects show it.
    - `id` (string, required): Unique ID of the team.
    - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
    - `name` (string, required): The team's display name.
    - `visibility` (string, one of: `open`, `private`, required): Who sees the team: open teams are listed for everyone in the workspace, private teams only for their members and for owners and admins.
  - `title` (string, required): A short name for the work.
  - `summary` (nullable string, required): What the work is and why, in Markdown, or null.
  - `status` (object, required): A step in a team's workflow, such as Todo or In Progress. See [the TicketStatus object](https://docs.qa.clankership.net/api/ticket-statuses/object.md).
    - `id` (string, required): Unique ID of the ticket status.
    - `name` (string, required): The status's name, unique within its team, such as In Progress.
    - `category` (string, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`, required): The fixed group the status belongs to: backlog, unstarted, started, completed or canceled. It cannot change.
    - `position` (number, required): Orders the status within its category; lower comes first.
    - `isDefault` (boolean, required): Whether new tickets get this status when none is named.
  - `owner` (nullable object, required): The agent that owns the ticket, or null.
    - `id` (string, required): Unique ID of the registered agent.
    - `name` (string, required): The coding agent, such as Codex.
    - `person` (object, required): A person in the workspace.
      - `id` (string, required): The person's user ID.
      - `name` (string, required): The person's display name.
      - `email` (string, required): The person's email address.
  - `project` (nullable object, required): The project the ticket belongs to, or null.
    - `id` (string, required): Unique ID of the project.
    - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
    - `name` (string, required): The project's display name.
  - `milestone` (nullable object, required): The milestone of its project the ticket belongs to, or null.
    - `id` (string, required): Unique ID of the milestone.
    - `number` (number, required): The milestone's number within the project: 2 is M2.
    - `name` (string, required): The milestone's name.
  - `tags` (array of objects, required): The ticket's tags, sorted by name. See [the Tag object](https://docs.qa.clankership.net/api/tags/object.md).
    - `id` (string, required): Unique ID of the tag.
    - `name` (string, required): The tag's name, such as bug.
    - `color` (string, one of: `gray`, `red`, `orange`, `amber`, `green`, `teal`, `cobalt`, `iris`, `pink`, required): The tag's color.
    - `team` (nullable object, required): The team a team tag belongs to; null for a workspace tag.
      - `id` (string, required): Unique ID of the team.
      - `key` (string, required): The team's key, such as WEB.
  - `rank` (number, required): The ticket's place in the one workspace-wide order that views ordered by hand follow; lower comes first.
  - `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
  - `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.
- `statuses` (array of objects, required): The columns a status grouping shows: the team's statuses, or the union across a project's teams. Matching names and categories share a column. See [the TicketStatus object](https://docs.qa.clankership.net/api/ticket-statuses/object.md).
  - `id` (string, required): Unique ID of the ticket status.
  - `name` (string, required): The status's name, unique within its team, such as In Progress.
  - `category` (string, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`, required): The fixed group the status belongs to: backlog, unstarted, started, completed or canceled. It cannot change.
  - `position` (number, required): Orders the status within its category; lower comes first.
  - `isDefault` (boolean, required): Whether new tickets get this status when none is named.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug}/teams/{team}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z",
  "tickets": [
    {
      "id": "Tk7BnC5xLp9M",
      "identifier": "WEB-31",
      "number": 31,
      "team": {
        "id": "Tm6PzN3kWq1J",
        "key": "WEB",
        "name": "Web",
        "visibility": "open"
      },
      "title": "Add docs search",
      "summary": "Readers cannot find a page without browsing the sidebar. Add a search box to the docs header.",
      "status": {
        "id": "St3IpV6nHs9D",
        "name": "In Progress",
        "category": "started",
        "position": 2,
        "isDefault": false
      },
      "owner": {
        "id": "Ag5HvB1mZr8K",
        "name": "Codex",
        "person": {
          "id": "Us3NfP8kLq2V",
          "name": "Maya Patel",
          "email": "maya@acme.dev"
        }
      },
      "project": {
        "id": "Pj2KsV8dRf4N",
        "slug": "docs-launch",
        "name": "Docs launch"
      },
      "milestone": {
        "id": "Ms2SrC9vLm4D",
        "number": 2,
        "name": "Search"
      },
      "tags": [
        {
          "id": "Tg3FtR7nWq2K",
          "name": "feature",
          "color": "cobalt",
          "team": null
        }
      ],
      "rank": 31.5,
      "createdAt": "2026-10-01T16:20:00.000Z",
      "updatedAt": "2026-10-14T09:05:12.000Z"
    }
  ],
  "statuses": [
    {
      "id": "St1BkL4pQx7N",
      "name": "Backlog",
      "category": "backlog",
      "position": 0,
      "isDefault": true
    },
    {
      "id": "St2TdW8mRc3K",
      "name": "Todo",
      "category": "unstarted",
      "position": 1,
      "isDefault": false
    },
    {
      "id": "St3IpV6nHs9D",
      "name": "In Progress",
      "category": "started",
      "position": 2,
      "isDefault": false
    },
    {
      "id": "St4IrG2wZf5M",
      "name": "In Review",
      "category": "started",
      "position": 3,
      "isDefault": false
    },
    {
      "id": "St5DnY7kPb1Q",
      "name": "Done",
      "category": "completed",
      "position": 4,
      "isDefault": false
    },
    {
      "id": "St6CnJ3xTe8L",
      "name": "Canceled",
      "category": "canceled",
      "position": 5,
      "isDefault": false
    },
    {
      "id": "St7DpR9vLw2H",
      "name": "Duplicate",
      "category": "canceled",
      "position": 6,
      "isDefault": false
    }
  ]
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Update a team view

`PATCH /v1/workspaces/{slug}/teams/{team}/views/{view}`

Changes only the settings sent, for everyone who opens the view; `filters` replaces the saved filters. Members of the team and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `team` (string, in path, required): The team's key, such as WEB.
- `view` (string, in path, required): The view's slug, such as active.
- `name` (string): The view's name, up to 60 characters, unique within its team or project. A new name gives the view a new slug.
- `filters` (object): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `none`): How the view groups tickets.
- `orderBy` (string, one of: `manual`, `created`, `updated`): `manual` follows the order people set by hand, `created` puts the newest first and `updated` the most recently changed.
- `layout` (string, one of: `list`, `board`): A list or a board.
- `isDefault` (boolean): `true` makes this the view the Tickets page opens. Always `true`.

### Returns

Returns the [View](https://docs.qa.clankership.net/api/views/object.md) object. The status is 200.

### Request

```bash
curl -X PATCH https://api.qa.clankership.net/v1/workspaces/{slug}/teams/{team}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "layout": "board",
    "isDefault": true
  }'
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Delete a team view

`DELETE /v1/workspaces/{slug}/teams/{team}/views/{view}`

Deletes the view. The default view stays until another view is the default. Members of the team and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `team` (string, in path, required): The team's key, such as WEB.
- `view` (string, in path, required): The view's slug, such as active.

### Returns

Returns no content. The status is 204.

### Request

```bash
curl -X DELETE https://api.qa.clankership.net/v1/workspaces/{slug}/teams/{team}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## List a project's views

`GET /v1/workspaces/{slug}/projects/{project}/views`

Returns the project's saved views. Every project starts with Board, its default, and All tickets.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `project` (string, in path, required): The project's slug, such as docs-launch.

### Returns

Returns an object with these fields. The status is 200.

- `views` (array of objects, required): The views, the default first, then in the order they were saved. See [the View object](https://docs.qa.clankership.net/api/views/object.md).
  - `id` (string, required): Unique ID of the view.
  - `slug` (string, required): Made from the view's name and unique within its team or project, such as active.
  - `name` (string, required): The view's name, such as Active.
  - `team` (nullable object, required): The team the view belongs to, or null for a project view.
    - `id` (string, required): Unique ID of the team.
    - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
    - `name` (string, required): The team's display name.
  - `project` (nullable object, required): The project the view belongs to, or null for a team view.
    - `id` (string, required): Unique ID of the project.
    - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
    - `name` (string, required): The project's display name.
  - `filters` (object, required): Which tickets a view shows. Filters combine with and; the values within one filter with or.
    - `statuses` (array of strings): Only tickets with these statuses, by name.
    - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
    - `tags` (array of strings): Only tickets with any of these tags, by name.
    - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
    - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
    - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
    - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
  - `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `milestone`, `team`, `none`, required): How the view groups tickets.
  - `orderBy` (string, one of: `manual`, `created`, `updated`, required): How the view orders tickets: manual follows the order people set by hand, created puts the newest first and updated the most recently changed.
  - `layout` (string, one of: `list`, `board`, required): Whether the view shows a list or a board.
  - `isDefault` (boolean, required): Whether the team's or project's Tickets page opens this view.
  - `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
  - `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug}/projects/{project}/views \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "views": [
    {
      "id": "Vw4AcT8nRk2P",
      "slug": "active",
      "name": "Active",
      "team": {
        "id": "Tm6PzN3kWq1J",
        "key": "WEB",
        "name": "Web"
      },
      "project": null,
      "filters": {
        "categories": [
          "unstarted",
          "started"
        ]
      },
      "groupBy": "status",
      "orderBy": "manual",
      "layout": "board",
      "isDefault": false,
      "createdAt": "2026-10-01T16:20:00.000Z",
      "updatedAt": "2026-10-14T09:05:12.000Z"
    }
  ]
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Create a project view

`POST /v1/workspaces/{slug}/projects/{project}/views`

Saves a view of the project's tickets, with a slug made from its name. Project views group by status, category, owner, tag, milestone, team or none. Members of the project's teams and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `project` (string, in path, required): The project's slug, such as docs-launch.
- `name` (string, required): The view's name, up to 60 characters, unique within its team or project.
- `filters` (object): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `milestone`, `team`, `none`): How the view groups tickets. Defaults to status.
- `orderBy` (string, one of: `manual`, `created`, `updated`): `manual` follows the order people set by hand, `created` puts the newest first and `updated` the most recently changed. Defaults to manual.
- `layout` (string, one of: `list`, `board`): A list or a board. Defaults to list.

### Returns

Returns the [View](https://docs.qa.clankership.net/api/views/object.md) object. The status is 201.

### Request

```bash
curl -X POST https://api.qa.clankership.net/v1/workspaces/{slug}/projects/{project}/views \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "By milestone",
    "filters": {
      "categories": [
        "unstarted",
        "started"
      ]
    },
    "groupBy": "milestone"
  }'
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Get a project view

`GET /v1/workspaces/{slug}/projects/{project}/views/{view}`

Returns the view with the tickets it shows, in its order. A status grouping uses the statuses the project's teams share as columns, or categories when their statuses differ.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `project` (string, in path, required): The project's slug, such as docs-launch.
- `view` (string, in path, required): The view's slug, such as active.

### Returns

Returns an object with these fields. The status is 200. A view with the tickets it shows.

- `id` (string, required): Unique ID of the view.
- `slug` (string, required): Made from the view's name and unique within its team or project, such as active.
- `name` (string, required): The view's name, such as Active.
- `team` (nullable object, required): The team the view belongs to, or null for a project view.
  - `id` (string, required): Unique ID of the team.
  - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
  - `name` (string, required): The team's display name.
- `project` (nullable object, required): The project the view belongs to, or null for a team view.
  - `id` (string, required): Unique ID of the project.
  - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
  - `name` (string, required): The project's display name.
- `filters` (object, required): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `project`, `milestone`, `team`, `none`, required): How the view groups tickets.
- `orderBy` (string, one of: `manual`, `created`, `updated`, required): How the view orders tickets: manual follows the order people set by hand, created puts the newest first and updated the most recently changed.
- `layout` (string, one of: `list`, `board`, required): Whether the view shows a list or a board.
- `isDefault` (boolean, required): Whether the team's or project's Tickets page opens this view.
- `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
- `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.
- `tickets` (array of objects, required): The tickets the view shows, in its order.
  - `id` (string, required): Unique ID of the ticket.
  - `identifier` (string, required): The team key and number, such as WEB-31. Paths take this ID.
  - `number` (number, required): The ticket's number within its team.
  - `team` (object, required): A team as tickets and projects show it.
    - `id` (string, required): Unique ID of the team.
    - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
    - `name` (string, required): The team's display name.
    - `visibility` (string, one of: `open`, `private`, required): Who sees the team: open teams are listed for everyone in the workspace, private teams only for their members and for owners and admins.
  - `title` (string, required): A short name for the work.
  - `summary` (nullable string, required): What the work is and why, in Markdown, or null.
  - `status` (object, required): A step in a team's workflow, such as Todo or In Progress. See [the TicketStatus object](https://docs.qa.clankership.net/api/ticket-statuses/object.md).
    - `id` (string, required): Unique ID of the ticket status.
    - `name` (string, required): The status's name, unique within its team, such as In Progress.
    - `category` (string, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`, required): The fixed group the status belongs to: backlog, unstarted, started, completed or canceled. It cannot change.
    - `position` (number, required): Orders the status within its category; lower comes first.
    - `isDefault` (boolean, required): Whether new tickets get this status when none is named.
  - `owner` (nullable object, required): The agent that owns the ticket, or null.
    - `id` (string, required): Unique ID of the registered agent.
    - `name` (string, required): The coding agent, such as Codex.
    - `person` (object, required): A person in the workspace.
      - `id` (string, required): The person's user ID.
      - `name` (string, required): The person's display name.
      - `email` (string, required): The person's email address.
  - `project` (nullable object, required): The project the ticket belongs to, or null.
    - `id` (string, required): Unique ID of the project.
    - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
    - `name` (string, required): The project's display name.
  - `milestone` (nullable object, required): The milestone of its project the ticket belongs to, or null.
    - `id` (string, required): Unique ID of the milestone.
    - `number` (number, required): The milestone's number within the project: 2 is M2.
    - `name` (string, required): The milestone's name.
  - `tags` (array of objects, required): The ticket's tags, sorted by name. See [the Tag object](https://docs.qa.clankership.net/api/tags/object.md).
    - `id` (string, required): Unique ID of the tag.
    - `name` (string, required): The tag's name, such as bug.
    - `color` (string, one of: `gray`, `red`, `orange`, `amber`, `green`, `teal`, `cobalt`, `iris`, `pink`, required): The tag's color.
    - `team` (nullable object, required): The team a team tag belongs to; null for a workspace tag.
      - `id` (string, required): Unique ID of the team.
      - `key` (string, required): The team's key, such as WEB.
  - `rank` (number, required): The ticket's place in the one workspace-wide order that views ordered by hand follow; lower comes first.
  - `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
  - `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.
- `statuses` (array of objects, required): The columns a status grouping shows: the team's statuses, or the union across a project's teams. Matching names and categories share a column. See [the TicketStatus object](https://docs.qa.clankership.net/api/ticket-statuses/object.md).
  - `id` (string, required): Unique ID of the ticket status.
  - `name` (string, required): The status's name, unique within its team, such as In Progress.
  - `category` (string, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`, required): The fixed group the status belongs to: backlog, unstarted, started, completed or canceled. It cannot change.
  - `position` (number, required): Orders the status within its category; lower comes first.
  - `isDefault` (boolean, required): Whether new tickets get this status when none is named.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug}/projects/{project}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z",
  "tickets": [
    {
      "id": "Tk7BnC5xLp9M",
      "identifier": "WEB-31",
      "number": 31,
      "team": {
        "id": "Tm6PzN3kWq1J",
        "key": "WEB",
        "name": "Web",
        "visibility": "open"
      },
      "title": "Add docs search",
      "summary": "Readers cannot find a page without browsing the sidebar. Add a search box to the docs header.",
      "status": {
        "id": "St3IpV6nHs9D",
        "name": "In Progress",
        "category": "started",
        "position": 2,
        "isDefault": false
      },
      "owner": {
        "id": "Ag5HvB1mZr8K",
        "name": "Codex",
        "person": {
          "id": "Us3NfP8kLq2V",
          "name": "Maya Patel",
          "email": "maya@acme.dev"
        }
      },
      "project": {
        "id": "Pj2KsV8dRf4N",
        "slug": "docs-launch",
        "name": "Docs launch"
      },
      "milestone": {
        "id": "Ms2SrC9vLm4D",
        "number": 2,
        "name": "Search"
      },
      "tags": [
        {
          "id": "Tg3FtR7nWq2K",
          "name": "feature",
          "color": "cobalt",
          "team": null
        }
      ],
      "rank": 31.5,
      "createdAt": "2026-10-01T16:20:00.000Z",
      "updatedAt": "2026-10-14T09:05:12.000Z"
    }
  ],
  "statuses": [
    {
      "id": "St1BkL4pQx7N",
      "name": "Backlog",
      "category": "backlog",
      "position": 0,
      "isDefault": true
    },
    {
      "id": "St2TdW8mRc3K",
      "name": "Todo",
      "category": "unstarted",
      "position": 1,
      "isDefault": false
    },
    {
      "id": "St3IpV6nHs9D",
      "name": "In Progress",
      "category": "started",
      "position": 2,
      "isDefault": false
    },
    {
      "id": "St4IrG2wZf5M",
      "name": "In Review",
      "category": "started",
      "position": 3,
      "isDefault": false
    },
    {
      "id": "St5DnY7kPb1Q",
      "name": "Done",
      "category": "completed",
      "position": 4,
      "isDefault": false
    },
    {
      "id": "St6CnJ3xTe8L",
      "name": "Canceled",
      "category": "canceled",
      "position": 5,
      "isDefault": false
    },
    {
      "id": "St7DpR9vLw2H",
      "name": "Duplicate",
      "category": "canceled",
      "position": 6,
      "isDefault": false
    }
  ]
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Update a project view

`PATCH /v1/workspaces/{slug}/projects/{project}/views/{view}`

Changes only the settings sent, for everyone who opens the view; `filters` replaces the saved filters. Members of the project's teams and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `project` (string, in path, required): The project's slug, such as docs-launch.
- `view` (string, in path, required): The view's slug, such as active.
- `name` (string): The view's name, up to 60 characters, unique within its team or project. A new name gives the view a new slug.
- `filters` (object): Which tickets a view shows. Filters combine with and; the values within one filter with or.
  - `statuses` (array of strings): Only tickets with these statuses, by name.
  - `categories` (array of strings, one of: `backlog`, `unstarted`, `started`, `completed`, `canceled`): Only tickets whose status is in these categories.
  - `tags` (array of strings): Only tickets with any of these tags, by name.
  - `owners` (array of strings): Only tickets these agents own, by agent ID; none matches tickets without an owner.
  - `projects` (array of strings): Only tickets in these projects, by slug; none matches tickets without a project. Team views only.
  - `milestones` (array of strings): Only tickets in these milestones, such as M1; none matches tickets without one. Project views only.
  - `teams` (array of strings): Only tickets of these teams, by key. Project views only.
- `groupBy` (string, one of: `status`, `category`, `owner`, `tag`, `milestone`, `team`, `none`): How the view groups tickets.
- `orderBy` (string, one of: `manual`, `created`, `updated`): `manual` follows the order people set by hand, `created` puts the newest first and `updated` the most recently changed.
- `layout` (string, one of: `list`, `board`): A list or a board.
- `isDefault` (boolean): `true` makes this the view the Tickets page opens. Always `true`.

### Returns

Returns the [View](https://docs.qa.clankership.net/api/views/object.md) object. The status is 200.

### Request

```bash
curl -X PATCH https://api.qa.clankership.net/v1/workspaces/{slug}/projects/{project}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "layout": "board",
    "isDefault": true
  }'
```

### Response

```json
{
  "id": "Vw4AcT8nRk2P",
  "slug": "active",
  "name": "Active",
  "team": {
    "id": "Tm6PzN3kWq1J",
    "key": "WEB",
    "name": "Web"
  },
  "project": null,
  "filters": {
    "categories": [
      "unstarted",
      "started"
    ]
  },
  "groupBy": "status",
  "orderBy": "manual",
  "layout": "board",
  "isDefault": false,
  "createdAt": "2026-10-01T16:20:00.000Z",
  "updatedAt": "2026-10-14T09:05:12.000Z"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Delete a project view

`DELETE /v1/workspaces/{slug}/projects/{project}/views/{view}`

Deletes the view. The default view stays until another view is the default. Members of the project's teams and workspace owners and admins change its views; viewers cannot.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `project` (string, in path, required): The project's slug, such as docs-launch.
- `view` (string, in path, required): The view's slug, such as active.

### Returns

Returns no content. The status is 204.

### Request

```bash
curl -X DELETE https://api.qa.clankership.net/v1/workspaces/{slug}/projects/{project}/views/{view} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.
