> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sempera.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Triage issues

> Tracking a problem with the calls that show it, files, comments and links between issues.

An issue is one problem your team is tracking with an agent: "callers asking for a colour correction are told we are closed". It carries a title, a severity and a category, a status on a small board, the calls that show the problem, attached files, links to other issues and an activity log.

Every issue belongs to one workspace. An issue id of another workspace answers `404` exactly like one that never existed. Reads need `evals:read`. Writes need `evals:write` and the `operator` or `owner` role; marking an issue viewed needs `evals:write` only.

These routes answer in the compatibility envelope: `{"data": ..., "errors": null}` on success and `{"data": null, "errors": [{"error", "message"}]}` on a refusal the route itself makes (`bad_request` 400, `not_found` 404, `conflict` 409). A missing credential, scope or role, a body that cannot be read as a JSON object, and an `agent_id` the credential cannot read (on create, and as the issues list filter) are refused with the standard error envelope ([Errors and limits](https://docs.sempera.org/errors-and-limits.md)). Lists page with `limit` and an opaque `next_cursor`; pass it back as `cursor` unchanged. The list routes refuse a query parameter they do not take; `GET /v1/triage/categories`, `GET /v1/triage/issues/{id}` and `GET .../affected` read none and ignore any you send. An issues list's cursor belongs to the filters and sort it was made with: change one between pages and the cursor is refused as invalid.

## Issues

| Route | Notes |
| - | - |
| `GET /v1/triage/issues` | `{"items", "next_cursor"}`. `limit` 1 to 100 (default 50); `sort` `last_activity_at` (default), `created_at`, `severity` or `status`; `order` `desc` (default) or `asc`; filters `search` (title and description), `status`, `severity`, `category` (each may repeat), `owner_id`, `assignee_id`, `agent_id`, and `date_range` (`24h`, `7d`, `30d`, `90d`) over `date_field` (`last_activity_at` or `created_at`) |
| `POST /v1/triage/issues` | Create. `201` |
| `GET /v1/triage/issues/{id}` | One issue |
| `PATCH /v1/triage/issues/{id}` | Change `title`, `description`, `status`, `severity`, `category`, `owner_id` or `assignee_id`. A status change is written to the activity log |
| `PUT /v1/triage/issues/{id}/view` | Mark the issue viewed by this credential: `{"issue_id", "last_viewed_at"}` |
| `GET /v1/triage/categories` | Every category this workspace's issues use, as `{"items", "next_cursor"}` (one unpaged list, `next_cursor` always null). An item is `id`, `name`, `org_id` and `created_at`, the date it was first used |

```http theme={null}
POST /v1/triage/issues
{"title": "Beard trim callers told we are closed", "severity": "high", "category": "booking", "agent_id": "northwind-barbers"}
```

| Field | Rule |
| - | - |
| `title` | Required, up to 200 characters |
| `severity` | Required: `critical`, `high`, `medium` or `low` |
| `category` | Required free text, up to 64 characters. There is no fixed list |
| `description` | Up to 10000 characters |
| `status` | `backlog`, `todo` (default), `in_progress`, `in_review`, `done` or `closed` |
| `source` | Create only: `manual` (default), `automated` or `client` |
| `agent_id` | Create only: an agent the credential can read |
| `owner_id`, `assignee_id` | An active member of the workspace, or null |
| `resource_links` | Create only: files to attach, each `{"resource_type": "file", "resource_id": "<file id>"}` |

An issue reads `id`, `triage_id` (`T-1001`, numbered per workspace), `number`, `org_id`, the fields above except `resource_links` (which is never returned), `author_id`, `created_at`, `updated_at`, `last_activity_at`, `resource_count`, `flag_count`, `relation_count` and `has_unread_activity` (true until this credential marks the issue viewed, and again after any later activity). `external_link` and `latest_agent_session` are always null and `is_processing` is always false. Creating an issue is also the `issue.created` event your automation triggers can listen for (`GET /v1/automation/events`).

## Evidence: calls

| Route | Notes |
| - | - |
| `GET /v1/triage/issues/{id}/flags` | The calls flagged onto the issue, newest first. `limit` 1 to 100 (default 50) and `cursor` |
| `POST /v1/triage/issues/{id}/flags` | `{"call_id", "type", "note"}`; `type` is `call` (default), `quality`, `routing` or `other`; `note` up to 2000 characters. `201`, or `409` when the call is already flagged on this issue |
| `PUT /v1/triage/issues/{id}/calls/{call_id}` | Link a call whether or not it is already linked (the idempotent form) |
| `GET /v1/triage/issues/{id}/affected` | What the issue touches: `issue_id`, its `calls` and the `personas` of every agent involved. `pathways` is always empty and `skill_context` names only the issue's `agent_id`, its other fields being null: Sempera has no pathways, skills or dispatch routing |
| `GET /v1/triage/flag-types` | The flag types this workspace has used, with `usage_count`, `last_used_at` and the latest non-empty note as `description`. `limit` 1 to 100 and `cursor` |

`call_id` names a conversation of an agent the credential can read; one it cannot read, or that does not exist, answers `404`. A flag reads `issue_id`, `call_id`, `agent_id`, `type`, `note`, `attached_by_id`, `org_id` and `created_at`.

## Files, comments, activity and links

| Route | Notes |
| - | - |
| `GET /v1/triage/issues/{id}/resources` | Attached files, newest first; `limit` 1 to 100. `status` is `unavailable` once the credential can no longer see the file. No `cursor` yet |
| `POST /v1/triage/issues/{id}/resources` | `{"resource_type": "file", "resource_id": "<file id>"}`. `201`, or `200` with the existing attachment; `404` for a file id that is not one the credential can see |
| `POST /v1/triage/issues/{id}/comments` | `{"detail": "..."}`, up to 10000 characters. `201` with the activity entry |
| `GET /v1/triage/issues/{id}/activity` | Comments, status changes, attached calls and link changes, newest first. `limit` 1 to 100 (default 100) and `cursor` |
| `GET /v1/triage/issues/{id}/relations` | Links to and from the issue. Each item names the other issue (`related_issue_id`, `related_triage_id`, `related_title`), the `relation_type` and `direction` (`outgoing` when this issue stored it). `limit` 1 to 100 and `cursor` |
| `POST /v1/triage/issues/{id}/relations` | `{"related_issue_id", "relation_type"}` with `related_to`, `blocks` or `duplicate_of`. `201`; `404` when the related issue does not exist or belongs to another workspace; `409` when the same link exists (the reverse of a `related_to` is the same link); an issue cannot link to itself |
| `DELETE /v1/triage/issues/{id}/relations/{relation_id}` | Remove a link from either side. `204` |

File ids are the `id` values `GET /v1/files/list` returns (`knowledge:read`), the knowledge documents of the agents the credential can read. Only files can be attached today.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.