# Test Execution API Workflow

This guide shows the full flow for starting a new test execution, checking the job that was created, and then loading the final test run report.

- You can use our [swagger](https://app.testifly.dev/swagger) interface to send requests and explore the API.
- You can also use any API client like Postman or Insomnia, or write your own scripts to automate the execution and reporting.

## 1. Start a new test execution

1. Send a request to `POST /api/testExecution/{projId}`.
2. Include your project API key in the `x-api-key` header.
3. Pass `action: "executeTests"` and add the filters that describe what should run.
4. If you have remote agents connected, you can also pass `agentName` to route the job to a specific runner.
5. Save the returned `jobId`, because you will use it to track the execution job.

The request body below starts a run for a feature. You can swap `featureId` for `testSuiteId`, `testId`, or `tests` depending on what you want to execute.

```
{
  "action": "executeTests",
  "featureId": "67f8cb3fe236b8d41b7700ac",
  "agentName": "my-agent"
}
```

The API response tells you whether the job was accepted and gives you the job identifier.

```
{
  "success": true,
  "scheduleStatus": "Success",
  "jobId": "6804f1d1d2d4e0a1c1a0d123"
}
```

### What the request fields mean

- `featureId` runs every test that belongs to one feature.
- `testSuiteId` runs every test in one test suite.
- `testId` runs one test.
- `tests` runs a custom list of test ids.
- `agentName` routes the job to a specific agent when you want to target one runner.

If the API returns `AlreadyExists`, the same execution job is already queued, so you should reuse the existing `jobId` instead of creating a duplicate run.

## 2. Monitor the job status

1. Send a request to `POST /api/jobs/{projId}`.
2. Pass the `jobIds` you want to inspect.
3. Poll this endpoint until the job reaches a terminal state.
4. Use the returned `testRunId` to open the final run report.

The request body below checks one job. You can include more job ids in the same array if you want to poll several executions at once.
You can also omit the `jobIds` field to get a list of all active jobs for the project from the last month, but that is not recommended for regular polling because the response will be larger and less efficient to process.

```
{
  "jobIds": ["6804f1d1d2d4e0a1c1a0d123"]
}
```

A typical status response contains the current job state, the last update time, and the linked test run id when it becomes available.

```
{
  "success": true,
  "jobs": [
    {
      "jobId": "6804f1d1d2d4e0a1c1a0d123",
      "status": "InProgress",
      "updatedAt": "2026-04-20T10:15:30.000Z",
      "testRunId": "6804f1e2d2d4e0a1c1a0d456"
    }
  ],
  "missingJobIds": []
}
```

### How to read the job status

- `Pending` means the job has been created and is waiting to start.
- `PendingAgentConnection` means the job is waiting for an agent to connect.
- `InProgress` means execution has started.
- `Success` or `Failed` means the job is finished.
- `updatedAt` tells you when the backend last changed the job record.
- `testRunId` appears when the execution has produced a test run record.
- `missingJobIds` lists ids that were invalid, missing, or did not belong to the project.

## 3. Monitor the test run status and result

1. Wait until the job response includes a `testRunId`.
2. Send a request to `GET /api/testRun/{projId}/{runId}`.
3. Read the overall run summary first, then inspect each test result.
4. Use the per-test status, timeline, and video link to understand what happened during execution.

The run report response gives you the full result set for the execution.

```
{
  "runId": "6804f1e2d2d4e0a1c1a0d456",
  "projectId": "67f8cb3fe236b8d41b7700ac",
  "status": "Completed",
  "startTime": "2026-04-20T10:15:31.000Z",
  "testsInProjectCount": 24,
  "title": "Regression run",
  "statuses": [
    {
      "label": "Passed",
      "count": 18
    },
    {
      "label": "Failed",
      "count": 2
    },
    {
      "label": "Skipped",
      "count": 4
    }
  ],
  "tests": [
    {
      "_id": "6804f1f1d2d4e0a1c1a0d789",
      "title": "Login works for valid users",
      "status": "Passed",
      "duration": 1240,
      "hasVideo": true,
      "videoLink": "https://example.com/videos/run-1",
      "startTime": "2026-04-20T10:15:40.000Z",
      "timeline": []
    }
  ]
}
```

### What to look for in the run report

- `status` shows the overall run state.
- `statuses` gives the summary counts for passed, failed, skipped, running, and scheduled tests.
- `tests` contains the individual test results.
- `duration` shows how long each test took.
- `timeline` helps you inspect the execution steps for a specific test.
- `videoLink` points to the recorded run when a video is available.
- `error` explains why a test failed when the execution did not succeed.

## 4. Suggested polling flow

1. Create the execution job.
2. Poll `/api/jobs/{projId}` until the job status becomes `InProgress` or `Success` and a `testRunId` is present.
3. Load `/api/testRun/{projId}/{runId}` with that `testRunId`.
4. Keep refreshing the run report if you want to watch live progress while the job is still running.

## 5. Authentication and access

All documented endpoints expect the project API key in the `x-api-key` header.

```
x-api-key: your_project_api_key
```

If the key is missing or invalid, the API rejects the request before it reaches the execution or status logic.

## 6. Quick reference

- `POST /api/testExecution/{projId}` starts a new execution.
- `POST /api/jobs/{projId}` checks execution job status.
- `GET /api/testRun/{projId}/{runId}` loads the final run report.

Use the job response to find the run id, then use the run report to inspect the final result details.
