# Traceability reports API

> Create traceability reports from Jira projects or GitHub repositories, generate their versions, and read the requirements of a ready version over the integrator API.

A traceability report covers the requirements of one tracker: the Jira issues of the projects and issue types you choose, or the GitHub issues of the repositories you choose. Each **version** of a report is a snapshot taken when it is generated: the matching requirements, their linked test cases, the latest results and the defects. The screens are described in [Traceability with Jira](https://docs.probara.net/en/guides/integrations/jira-traceability/) and [Traceability with GitHub](https://docs.probara.net/en/guides/integrations/github/#traceability-with-github).

Every endpoint is under `/api/v1/projects/{projectId}/traceability`, where `{projectId}` is the project **code** (for example `ACME`). The endpoints need the Pro or Enterprise plan; on other plans they answer `403 forbidden`. Reading needs access to the project. Creating, generating, renaming and deleting need the `test-cases.write` permission, the same one that links test cases to Jira issues.

| Method and path                                                 | What it does                                                                                                                                                      |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /sources`                                                  | Lists the organization's active Jira and GitHub connections, each with its `provider`. An empty list means no integration is active, so no report can be created. |
| `GET /sources/{connectionUlid}/projects`                        | Lists the Jira projects that connection allows, read live from Jira.                                                                                              |
| `GET /sources/{connectionUlid}/issue-types?projects=WEB,API`    | Lists the distinct issue type names of the given Jira projects, sorted.                                                                                           |
| `GET /sources/{connectionUlid}/repositories`                    | GitHub: lists the repositories a report may read through that connection.                                                                                         |
| `GET /sources/{connectionUlid}/labels?repository=acme/shop`     | GitHub: lists the repository's label names.                                                                                                                       |
| `GET /sources/{connectionUlid}/milestones?repository=acme/shop` | GitHub: lists the repository's milestones, open and closed, with `title` and `state`.                                                                             |
| `GET /reports`                                                  | Lists the project's reports, newest first.                                                                                                                        |
| `POST /reports`                                                 | Saves a report and queues its first version. Answers `201`.                                                                                                       |
| `GET /reports/{reportUlid}`                                     | Reads one report.                                                                                                                                                 |
| `PATCH /reports/{reportUlid}`                                   | Renames a report.                                                                                                                                                 |
| `DELETE /reports/{reportUlid}`                                  | Deletes the report and all its versions. Answers `204`.                                                                                                           |
| `GET /reports/{reportUlid}/versions`                            | Lists the report's versions, newest first.                                                                                                                        |
| `POST /reports/{reportUlid}/versions`                           | Queues a new version with the report's projects and issue types. Answers `201`.                                                                                   |
| `GET /versions/{versionUlid}`                                   | Reads a version: its status and totals and, once it is ready, the totals of each project.                                                                         |
| `PATCH /versions/{versionUlid}`                                 | Renames a version. `null` clears the name.                                                                                                                        |
| `DELETE /versions/{versionUlid}`                                | Deletes the version. Answers `204`.                                                                                                                               |
| `GET /versions/{versionUlid}/requirements`                      | Lists one tab of a ready version, with filters and page-based pagination.                                                                                         |

## Choose the sources

`POST /reports` takes the connection ULID from `GET /sources` and the project keys that `GET /sources/{connectionUlid}/projects` returns. Issue type names come from `GET /sources/{connectionUlid}/issue-types`.

## Create a report

`POST /reports` takes:

| Field                | Rule                                                                                                                                                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`               | Required, 1 to 200 characters after trimming.                                                                                                                                                                                                           |
| `filters.provider`   | `jira`. For a GitHub report, `github` with other filters: see [GitHub reports](#github-reports).                                                                                                                                                        |
| `filters.projects`   | Required, 1 to 20 objects with `connectionUlid` and `projectKey`, without duplicates. Each project must be allowed by an active connection of the organization. Otherwise the request answers `422 traceability_project_not_allowed` and saves nothing. |
| `filters.issueTypes` | Optional, up to 50 names. Omitted or empty means every issue type of the projects. Names compare without regard to letter case, and duplicates collapse.                                                                                                |

The `201` response holds the `report` and its first `version`, whose status is `pending`. Read the version until its status is `ready`.

## GitHub reports

A report with `filters.provider: "github"` reads the issues of up to 20 repositories:

```json
{
  "name": "Checkout requirements",
  "filters": {
    "provider": "github",
    "repositories": [{ "connectionUlid": "01J9Z3K4M5N6P7Q8R9S0T1V2W3", "fullName": "acme/shop" }],
    "labels": ["requirement"],
    "milestone": "v2.0",
    "state": "all"
  }
}
```

| Field                  | Rule                                                                                                                                                                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `filters.repositories` | Required, 1 to 20, from `GET /sources/{connectionUlid}/repositories`: the project's repository mapping on that connection, or every repository it can see when the project maps none. Otherwise `403 github_repository_not_mapped` or `422 github_repository_not_visible`, and nothing is saved. |
| `filters.labels`       | Optional, up to 20 names without commas. An issue must carry every one of them. Empty keeps every issue.                                                                                                                                                                                         |
| `filters.milestone`    | Optional milestone title, in any letter case. A repository without a milestone of that title contributes no issues.                                                                                                                                                                              |
| `filters.state`        | `open`, `closed` or `all` (default).                                                                                                                                                                                                                                                             |

The repositories are checked again when each version is generated. Pull requests are never
requirements. A requirement's key is `owner/name#number`, its `projectKey` is `owner/name`, its type
is `Issue` and its status is `Open`, `Closed` or `Closed as not planned`, in the status categories
`to_do` (open) or `done` (closed). A GitHub requirement is **linked** when a test case of the project
links the issue as a `requirement` (see the [GitHub API](https://docs.probara.net/en/developers/api/github/#link-issues)).

## Versions

A version has these fields:

- `status`: `pending`, `generating`, `ready` or `failed`.
- `number`: 1, 2, 3 and so on within the report. A deleted version's number is never reused.
- `name`: the name given by renaming, or `null` to show it as `Version {number}`.
- `totals`: `requirements`, `linked` and `unlinked`. `null` until the version is ready.
- `errorCode`, for a failed version: `connection_unavailable` when a selected project's connection was removed, paused or no longer allows the project; `requirements_limit_exceeded` when the filters match more than 5,000 requirements; `provider_error` when Jira could not be read.
- `createdAt` and `generatedAt`: epoch milliseconds. `generatedAt` is `null` until the version is ready.

A version is never changed once it is ready. Only one version of a report can be pending or generating at a time: a `POST /reports/{reportUlid}/versions` made while another one is open answers `409 traceability_version_in_progress`.

`GET /versions/{versionUlid}` also returns `report` (its ULID, name and filters) and `projects`: one entry per selected project, in the report's order, with its `connectionUlid`, `projectKey`, `name` and the `requirements`, `linked` and `unlinked` counts. `projects` is empty until the version is ready.

## Requirements

`GET /versions/{versionUlid}/requirements` answers one tab of a ready version. A version that is not ready answers `409 traceability_version_not_ready`.

| Parameter      | Meaning                                                                                                                          |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `tab`          | `linked` (default) or `unlinked`.                                                                                                |
| `q`            | Up to 200 characters. Matches the Jira key exactly, in any letter case, or a case-insensitive part of the title or the key.      |
| `projectKey`   | Only requirements of this Jira project.                                                                                          |
| `status`       | Comma-separated status categories: `to_do`, `in_progress`, `done`.                                                               |
| `resultStatus` | Comma-separated latest results of the linked cases: `passed`, `failed`, `skipped`, `blocked`, `untested`. Ignored on `unlinked`. |
| `defectStatus` | Comma-separated statuses of the linked defects: `open`, `in_progress`, `resolved`, `closed`. Ignored on `unlinked`.              |
| `page`         | From 1. Default 1. A page past the last one has no items.                                                                        |
| `pageSize`     | From 1 to 100. Default 25.                                                                                                       |

Filters combine with AND, and the values inside one filter combine with OR.

A requirement is **linked** when at least one test case of the project links it, archived cases included. The `unlinked` tab holds the others.

The response has `items`, `page`, `pageSize` and `total` (the requirements that match every filter, over all pages). A version never changes once it is ready, so consecutive pages never overlap. Each requirement carries its Jira identifiers and URL, its `statusName` and `statusCategory`, its `updatedAt` as read when the version was generated, its `caseCount`, its `staleCaseCount`, its `defects` (`total`, the distinct defects linked to its cases, and `byStatus`, the same defects counted by current status: `open`, `in_progress`, `resolved` and `closed`), and up to 200 `cases`, with `casesTruncated` when more exist. Each case carries its `displayId`, `title`, `archived` flag, `caseUpdatedAt`, `stale` flag, `latestResult` (or `null`), and up to 20 `defects`, with `defectsTruncated` when more exist.

## Rate limits

Reading a connection's projects or issue types, creating reports and creating versions are rate limited per organization. A `429 too_many_requests` response includes `Retry-After`.

## Errors

Every error uses the [standard error envelope](https://docs.probara.net/en/developers/api-reference/#errors).

| Status | Code                               | When                                                                                                                   |
| ------ | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `403`  | `forbidden`                        | The plan does not include integrations, or your role lacks `test-cases.write` on a create, generate, rename or delete. |
| `403`  | `github_repository_not_mapped`     | GitHub: the project's repository mapping leaves the repository out.                                                    |
| `409`  | `github_connection_stale`          | GitHub: the installation was suspended or uninstalled.                                                                 |
| `422`  | `github_repository_not_visible`    | GitHub: the installation cannot see the repository.                                                                    |
| `503`  | `github_unavailable`               | GitHub cannot be reached right now.                                                                                    |
| `403`  | `jira_project_not_allowed`         | The connection does not allow the Jira project asked for.                                                              |
| `403`  | `jira_permission_denied`           | Jira refused the read for the connection's account.                                                                    |
| `404`  | `not_found`                        | No report, version or connection with that ULID that you can see.                                                      |
| `404`  | `jira_not_found`                   | Jira does not find the project or issue type asked for.                                                                |
| `409`  | `jira_connection_stale`            | The Jira connection is stale. Check it in the integration settings.                                                    |
| `409`  | `traceability_version_in_progress` | Another version of the report is pending or generating.                                                                |
| `409`  | `traceability_version_not_ready`   | Requirements were requested from a version that is not ready.                                                          |
| `422`  | `traceability_project_not_allowed` | A selected project is not allowed by an active connection. Nothing is saved.                                           |
| `422`  | `validation_failed`                | The body, a query parameter or a path parameter is malformed.                                                          |
| `429`  | `too_many_requests`                | The rate limit of the reads or writes listed above is reached. `Retry-After` says when to retry.                       |
| `503`  | `jira_unavailable`                 | Jira cannot be reached right now.                                                                                      |
| `503`  | `jira_rate_limited`                | Jira is throttling requests. `Retry-After` says when to retry.                                                         |
