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

# Test Runs

> Record verification campaigns and generate AI analysis reports.

A test run is a record of a verification campaign against a design or asset. It gathers test cards (individual test cases), the data behind them, and Atlas's analysis of how things performed.

See [Creating a Test Run Report](/guides/test-runs) for a workflow guide.

## Endpoints

| Method   | Path                                                  | Description               |
| -------- | ----------------------------------------------------- | ------------------------- |
| `POST`   | `/test-runs`                                          | Create a test run         |
| `GET`    | `/test-runs`                                          | List test runs            |
| `GET`    | `/test-runs/search`                                   | Search test runs          |
| `GET`    | `/test-runs/{run_id}`                                 | Get a test run            |
| `PATCH`  | `/test-runs/{run_id}`                                 | Update a test run         |
| `DELETE` | `/test-runs/{run_id}`                                 | Delete a test run         |
| `POST`   | `/test-runs/{run_id}/data`                            | Register a data file      |
| `GET`    | `/test-runs/{run_id}/data`                            | List data files           |
| `DELETE` | `/test-runs/{run_id}/data/{file_id}`                  | Delete a data file        |
| `POST`   | `/test-runs/{run_id}/cards`                           | Create a test card        |
| `PATCH`  | `/test-runs/{run_id}/cards/{card_id}`                 | Update a test card        |
| `DELETE` | `/test-runs/{run_id}/cards/{card_id}`                 | Delete a test card        |
| `POST`   | `/test-runs/{run_id}/cards/{card_id}/steps`           | Create a step             |
| `PATCH`  | `/test-runs/{run_id}/cards/{card_id}/steps/{step_id}` | Update a step             |
| `DELETE` | `/test-runs/{run_id}/cards/{card_id}/steps/{step_id}` | Delete a step             |
| `POST`   | `/test-runs/{run_id}/reports`                         | Create an analysis report |
| `GET`    | `/test-runs/{run_id}/reports`                         | List reports              |
| `GET`    | `/test-runs/{run_id}/reports/{report_id}`             | Get a report              |

***

## Create a test run

`POST /test-runs`

**Request body:**

| Field          | Required | Type          | Description                          |
| -------------- | -------- | ------------- | ------------------------------------ |
| `title`        | Yes      | string        | Display name for the test run        |
| `system_id`    | Yes      | UUID          | System this run is scoped to         |
| `description`  | No       | string        | Additional context. Defaults to `""` |
| `asset_ids`    | No       | array of UUID | Physical assets under test           |
| `issue_ids`    | No       | array of UUID | Issues associated with this run      |
| `template_ids` | No       | array of UUID | Card templates to instantiate        |

**Example request:**

```bash theme={null}
curl -X POST "https://nokia.atlas.arenaphysica.com/api/v1/test-runs" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Motor Controller Acceptance Test",
    "system_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }'
```

**Response fields:**

| Field          | Type   | Nullable | Description                    |
| -------------- | ------ | -------- | ------------------------------ |
| `uuid`         | string | No       | Test run identifier            |
| `test_run_id`  | string | No       | Human-readable run ID          |
| `title`        | string | No       | Display name                   |
| `description`  | string | No       | Description                    |
| `system_id`    | string | No       | Associated system              |
| `system_name`  | string | No       | System display name            |
| `test_cards`   | array  | No       | List of test card objects      |
| `test_data`    | array  | No       | Registered data files          |
| `reports`      | array  | No       | Analysis reports               |
| `contributors` | array  | No       | Emails of contributors         |
| `created_by`   | string | No       | Creator email                  |
| `created_at`   | string | No       | ISO 8601 creation timestamp    |
| `updated_at`   | string | No       | ISO 8601 last-update timestamp |

**Example response:**

```json theme={null}
{
  "uuid": "c9d0e1f2-a3b4-5678-cdef-789012345678",
  "test_run_id": "TR-0042",
  "title": "Motor Controller Acceptance Test",
  "description": "",
  "system_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "system_name": "Power Distribution Unit",
  "test_cards": [],
  "test_data": [],
  "reports": [],
  "contributors": ["engineer@example.com"],
  "created_by": "engineer@example.com",
  "created_at": "2026-04-13T11:00:00.000000",
  "updated_at": "2026-04-13T11:00:00.000000"
}
```

***

## List test runs

`GET /test-runs`

**Query parameters:**

| Parameter        | Type    | Description                                              |
| ---------------- | ------- | -------------------------------------------------------- |
| `system_id`      | UUID    | Filter by system                                         |
| `created_after`  | string  | ISO 8601 lower bound                                     |
| `created_before` | string  | ISO 8601 upper bound                                     |
| `has_reports`    | boolean | Filter to runs that have (or have not) generated reports |

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs?system_id=$SYSTEM_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

**Response fields (each item):**

| Field                | Type            | Description                            |
| -------------------- | --------------- | -------------------------------------- |
| `uuid`               | string          | Test run identifier                    |
| `test_run_id`        | string          | Human-readable run ID (e.g. `TR-0042`) |
| `title`              | string          | Display name                           |
| `system_id`          | string          | Associated system                      |
| `system_name`        | string          | System display name                    |
| `completion_pct`     | float           | Percentage of steps completed          |
| `step_status_counts` | object          | Count of steps per execution status    |
| `contributors`       | array of string | Emails of contributors                 |
| `asset_names`        | array of string | Names of linked assets                 |
| `asset_count`        | integer         | Number of linked assets                |
| `issue_count`        | integer         | Number of linked issues                |
| `card_count`         | integer         | Number of test cards                   |
| `file_count`         | integer         | Number of registered data files        |
| `report_count`       | integer         | Number of generated reports            |
| `created_by`         | string          | Creator email                          |
| `created_at`         | string          | ISO 8601 creation timestamp            |
| `updated_at`         | string          | ISO 8601 last-update timestamp         |

**Example response:**

```json theme={null}
{
  "items": [
    {
      "uuid": "c9d0e1f2-a3b4-5678-cdef-789012345678",
      "test_run_id": "TR-0042",
      "title": "Motor Controller Acceptance Test",
      "system_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "system_name": "Power Distribution Unit",
      "completion_pct": 0.75,
      "step_status_counts": {"todo": 1, "passed": 3},
      "contributors": ["engineer@example.com"],
      "asset_names": [],
      "asset_count": 0,
      "issue_count": 1,
      "card_count": 4,
      "file_count": 2,
      "report_count": 1,
      "created_by": "engineer@example.com",
      "created_at": "2026-04-13T11:00:00.000000",
      "updated_at": "2026-04-13T11:30:00.000000"
    }
  ],
  "count": 1
}
```

***

## Search test runs

`GET /test-runs/search`

Full-text and semantic search across test runs, cards, steps, and reports.

**Query parameters:**

| Parameter         | Required | Type                | Description                                                 |
| ----------------- | -------- | ------------------- | ----------------------------------------------------------- |
| `q`               | Yes      | string              | Search query                                                |
| `mode`            | No       | string              | Search mode: `default` (default)                            |
| `component_types` | No       | string (repeatable) | Restrict to component types (e.g. `card`, `step`, `report`) |
| `system_id`       | No       | UUID                | Filter to a specific system                                 |
| `created_after`   | No       | string              | ISO 8601 lower bound                                        |
| `created_before`  | No       | string              | ISO 8601 upper bound                                        |
| `has_reports`     | No       | boolean             | Filter to runs with (or without) reports                    |
| `sort_by`         | No       | string              | `relevance` (default)                                       |
| `limit`           | No       | integer             | Default `20`, max `100`                                     |
| `offset`          | No       | integer             | Default `0`                                                 |

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/search?q=undervoltage&system_id=$SYSTEM_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

**Response fields:**

| Field         | Type    | Description                   |
| ------------- | ------- | ----------------------------- |
| `results`     | array   | List of search result objects |
| `total_count` | integer | Total number of matching runs |

Each result object:

| Field      | Type   | Description                                     |
| ---------- | ------ | ----------------------------------------------- |
| `test_run` | object | Test run summary (same fields as list response) |
| `score`    | float  | Relevance score                                 |
| `matches`  | array  | Matched components within the run               |

Each match object:

| Field             | Type   | Description                                               |
| ----------------- | ------ | --------------------------------------------------------- |
| `component_type`  | string | Type of matched component (e.g. `card`, `step`, `report`) |
| `component_id`    | string | Identifier of the matched component                       |
| `component_title` | string | Title of the matched component                            |
| `path`            | string | Human-readable path within the run                        |
| `snippet`         | string | Matching text excerpt                                     |
| `match_type`      | string | `fulltext` or `semantic`                                  |

**Example response:**

```json theme={null}
{
  "results": [
    {
      "test_run": {
        "uuid": "c9d0e1f2-a3b4-5678-cdef-789012345678",
        "test_run_id": "TR-0042",
        "title": "Motor Controller Acceptance Test",
        "system_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "system_name": "Power Distribution Unit",
        "completion_pct": 0.75,
        "card_count": 4,
        "report_count": 1,
        "created_by": "engineer@example.com",
        "created_at": "2026-04-13T11:00:00.000000"
      },
      "score": 0.92,
      "matches": [
        {
          "component_type": "step",
          "component_id": "d0e1f2a3-b4c5-6789-defa-890123456789",
          "component_title": "Apply 13V to input rail",
          "path": "Overvoltage protection > Apply 13V to input rail",
          "snippet": "Verify shutdown within 100ms after undervoltage event",
          "match_type": "semantic"
        }
      ]
    }
  ],
  "total_count": 1
}
```

***

## Get a test run

`GET /test-runs/{run_id}`

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns a test run detail object with the same fields as the [create response](#create-a-test-run).

***

## Update a test run

`PATCH /test-runs/{run_id}`

All fields are optional.

| Field         | Type   | Description          |
| ------------- | ------ | -------------------- |
| `title`       | string | Updated display name |
| `description` | string | Updated description  |

**Example request:**

```bash theme={null}
curl -X PATCH "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Motor Controller Acceptance Test – Rev 2"}'
```

Returns the updated test run detail object with the same fields as the [create response](#create-a-test-run).

***

## Delete a test run

`DELETE /test-runs/{run_id}`

**Example request:**

```bash theme={null}
curl -X DELETE "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns **204 No Content**.

***

## Register a data file

`POST /test-runs/{run_id}/data`

Registers a data file that is already stored in S3. The file must exist at the provided S3 URL before calling this endpoint.

**Request body:**

| Field            | Required | Type    | Description                                                                        |
| ---------------- | -------- | ------- | ---------------------------------------------------------------------------------- |
| `file_name`      | Yes      | string  | Display name for the file                                                          |
| `s3_url`         | Yes      | string  | S3 URL of the uploaded file                                                        |
| `file_size`      | Yes      | integer | File size in bytes                                                                 |
| `content_type`   | No       | string  | MIME type. Defaults to `"application/octet-stream"`                                |
| `associate_with` | No       | object  | Associate this file with a specific card or step: `{test_card_id?, test_step_id?}` |

**Example request:**

```bash theme={null}
curl -X POST "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/data" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "file_name": "motor_test_log.csv",
    "s3_url": "s3://your-bucket/test-data/motor_test_log.csv",
    "file_size": 204800,
    "content_type": "text/csv"
  }'
```

**Response fields:**

| Field          | Type    | Nullable | Description                                  |
| -------------- | ------- | -------- | -------------------------------------------- |
| `uuid`         | string  | No       | File record identifier                       |
| `file_name`    | string  | No       | Display name                                 |
| `s3_url`       | string  | No       | S3 location                                  |
| `file_size`    | integer | No       | Size in bytes                                |
| `content_type` | string  | No       | MIME type                                    |
| `uploaded_by`  | string  | No       | Uploader email                               |
| `created_at`   | string  | No       | ISO 8601 registration timestamp              |
| `associations` | array   | No       | List of card/step associations for this file |

**Example response:**

```json theme={null}
{
  "uuid": "b1c2d3e4-f5a6-7890-bcde-234567890123",
  "file_name": "motor_test_log.csv",
  "s3_url": "s3://your-bucket/test-data/motor_test_log.csv",
  "file_size": 204800,
  "content_type": "text/csv",
  "uploaded_by": "engineer@example.com",
  "created_at": "2026-04-13T11:02:00.000000",
  "associations": []
}
```

***

## List data files

`GET /test-runs/{run_id}/data`

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/data" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns `{"items": [...], "count": N}` where each item is a data file object with the same fields as the [register response](#register-a-data-file).

***

## Delete a data file

`DELETE /test-runs/{run_id}/data/{file_id}`

**Example request:**

```bash theme={null}
curl -X DELETE "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/data/$FILE_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns **204 No Content**.

***

## Create a test card

`POST /test-runs/{run_id}/cards`

A test card is an individual test case within a run.

**Request body:**

| Field         | Required    | Type    | Description                                                  |
| ------------- | ----------- | ------- | ------------------------------------------------------------ |
| `title`       | Conditional | string  | Card title. Required if `template_id` is not provided        |
| `template_id` | Conditional | UUID    | Template to instantiate. Required if `title` is not provided |
| `description` | No          | string  | Card description. Defaults to `""`                           |
| `order`       | No          | integer | Display order                                                |

**Example request:**

```bash theme={null}
curl -X POST "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Overvoltage protection",
    "description": "Apply 13V to input, verify shutdown within 100ms"
  }'
```

**Response fields:**

| Field         | Type    | Description                                              |
| ------------- | ------- | -------------------------------------------------------- |
| `uuid`        | string  | Card identifier                                          |
| `title`       | string  | Card title                                               |
| `description` | string  | Card description                                         |
| `order`       | integer | Display order                                            |
| `test_steps`  | array   | List of step objects (see Update a step for step fields) |
| `issues`      | array   | Linked issue references                                  |
| `test_data`   | array   | Linked data files                                        |
| `reports`     | array   | Report summaries linked to this card                     |
| `created_at`  | string  | ISO 8601 creation timestamp                              |
| `updated_at`  | string  | ISO 8601 last-update timestamp                           |

**Example response:**

```json theme={null}
{
  "uuid": "d2e3f4a5-b6c7-8901-defa-345678901234",
  "title": "Overvoltage protection",
  "description": "Apply 13V to input, verify shutdown within 100ms",
  "order": 1,
  "test_steps": [],
  "issues": [],
  "test_data": [],
  "reports": [],
  "created_at": "2026-04-13T11:03:00.000000",
  "updated_at": "2026-04-13T11:03:00.000000"
}
```

***

## Update a test card

`PATCH /test-runs/{run_id}/cards/{card_id}`

All fields are optional.

| Field         | Type   | Description         |
| ------------- | ------ | ------------------- |
| `title`       | string | Updated card title  |
| `description` | string | Updated description |

**Example request:**

```bash theme={null}
curl -X PATCH "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards/$CARD_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Overvoltage protection – updated threshold"}'
```

Returns the updated test card object with the same fields as the [create card response](#create-a-test-card).

***

## Delete a test card

`DELETE /test-runs/{run_id}/cards/{card_id}`

**Example request:**

```bash theme={null}
curl -X DELETE "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards/$CARD_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns **204 No Content**.

***

## Create a step

`POST /test-runs/{run_id}/cards/{card_id}/steps`

**Request body:**

| Field         | Required | Type    | Description                                    |
| ------------- | -------- | ------- | ---------------------------------------------- |
| `title`       | Yes      | string  | Step title (max 100 characters)                |
| `description` | No       | string  | Step description. Defaults to `""`             |
| `step_type`   | No       | string  | `passfail` (default) or other configured types |
| `order`       | No       | integer | Display order                                  |

**Example request:**

```bash theme={null}
curl -X POST "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards/$CARD_ID/steps" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Apply 13V to input rail"}'
```

Returns a step object with the same fields as the [update step response](#update-a-step).

***

## Update a step

`PATCH /test-runs/{run_id}/cards/{card_id}/steps/{step_id}`

Update step metadata or record an execution outcome.

**Request body:**

| Field              | Type   | Description                                                 |
| ------------------ | ------ | ----------------------------------------------------------- |
| `title`            | string | Step title                                                  |
| `description`      | string | Step description                                            |
| `execution_status` | string | `todo`, `done`, `passed`, `passed_with_exception`, `failed` |
| `exception`        | string | Exception note for `passed_with_exception`                  |
| `started_at`       | string | ISO 8601 start time                                         |
| `ended_at`         | string | ISO 8601 end time                                           |

**Example request:**

```bash theme={null}
curl -X PATCH "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards/$CARD_ID/steps/$STEP_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"execution_status": "passed"}'
```

**Response fields:**

| Field              | Type    | Description                                                 |
| ------------------ | ------- | ----------------------------------------------------------- |
| `uuid`             | string  | Step identifier                                             |
| `title`            | string  | Step title                                                  |
| `description`      | string  | Step description                                            |
| `order`            | integer | Display order                                               |
| `step_type`        | string  | Step type                                                   |
| `execution_status` | string  | `todo`, `done`, `passed`, `passed_with_exception`, `failed` |
| `exception`        | string  | Exception note (if `passed_with_exception`)                 |
| `started_at`       | string  | ISO 8601 start time                                         |
| `ended_at`         | string  | ISO 8601 end time                                           |
| `observations`     | array   | Observations recorded on this step                          |
| `test_data`        | array   | Data files linked to this step                              |
| `issues`           | array   | Issues linked to this step                                  |
| `reports`          | array   | Report summaries linked to this step                        |
| `created_at`       | string  | ISO 8601 creation timestamp                                 |
| `updated_at`       | string  | ISO 8601 last-update timestamp                              |

**Example response:**

```json theme={null}
{
  "uuid": "e3f4a5b6-c7d8-9012-efab-456789012345",
  "title": "Apply 13V to input rail",
  "description": "",
  "order": 1,
  "step_type": "passfail",
  "execution_status": "passed",
  "exception": null,
  "started_at": null,
  "ended_at": null,
  "observations": [],
  "test_data": [],
  "issues": [],
  "reports": [],
  "created_at": "2026-04-13T11:04:00.000000",
  "updated_at": "2026-04-13T11:10:00.000000"
}
```

***

## Delete a step

`DELETE /test-runs/{run_id}/cards/{card_id}/steps/{step_id}`

**Example request:**

```bash theme={null}
curl -X DELETE "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/cards/$CARD_ID/steps/$STEP_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns **204 No Content**.

***

## List reports

`GET /test-runs/{run_id}/reports`

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/reports" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns `{"items": [...], "count": N}` where each item is a report object with the same fields as the [create report response](#create-a-report).

***

## Get a report

`GET /test-runs/{run_id}/reports/{report_id}`

**Example request:**

```bash theme={null}
curl "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/reports/$REPORT_ID" \
  -H "Authorization: Bearer $ATLAS_TOKEN"
```

Returns a report object with the same fields as the [create report response](#create-a-report).

***

## Create a report

`POST /test-runs/{run_id}/reports`

Triggers an AI analysis of the registered data files and produces a structured report.

**Request body:**

| Field              | Required    | Type   | Description                                           |
| ------------------ | ----------- | ------ | ----------------------------------------------------- |
| `scope`            | Yes         | string | Report scope: `run`, `card`, or `step`                |
| `test_card_id`     | Conditional | UUID   | Required when `scope` is `card` or `step`             |
| `test_step_id`     | Conditional | UUID   | Required when `scope` is `step`                       |
| `analysis_context` | No          | string | Free-text guidance for the analysis. Defaults to `""` |

**Example request:**

```bash theme={null}
curl -X POST "https://nokia.atlas.arenaphysica.com/api/v1/test-runs/$RUN_ID/reports" \
  -H "Authorization: Bearer $ATLAS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"scope": "run"}'
```

**Response fields:**

| Field        | Type   | Nullable | Description                                              |
| ------------ | ------ | -------- | -------------------------------------------------------- |
| `uuid`       | string | No       | Report identifier                                        |
| `title`      | string | No       | Auto-generated report title                              |
| `scope`      | string | No       | `run`, `card`, or `step`                                 |
| `status`     | string | No       | `pending`, `running`, `completed`, `failed`, `cancelled` |
| `content`    | string | No       | Full report text (populated when `completed`)            |
| `summary`    | string | No       | Short summary (populated when `completed`)               |
| `issues`     | array  | No       | Issues linked to this report                             |
| `test_data`  | array  | No       | Data files analyzed                                      |
| `job_run_id` | string | Yes      | Background job that generated this report                |
| `created_by` | string | No       | Creator email                                            |
| `created_at` | string | No       | ISO 8601 creation timestamp                              |

**Example response:**

```json theme={null}
{
  "uuid": "d0e1f2a3-b4c5-6789-defa-890123456789",
  "title": "Motor Controller Acceptance Test – Run Analysis",
  "scope": "run",
  "status": "pending",
  "content": "",
  "summary": "",
  "issues": [],
  "test_data": [],
  "job_run_id": "e1f2a3b4-c5d6-7890-efab-901234567890",
  "created_by": "engineer@example.com",
  "created_at": "2026-04-13T11:05:00.000000"
}
```

Poll `GET /test-runs/{run_id}/reports/{report_id}` until `status` is `completed`.
