# Runs API

Source: https://userguide.qualytics.io/operations/runs/api/

The endpoints documented on this page are used to **manage** existing Runs: list them, fetch a single Run, abort an in-flight Run, resume or rerun a finished one, and delete a Run record. For payload examples to **create** a new Run, see the API page for the specific operation type (for example, [Scan API](https://userguide.qualytics.io/operations/scan/api/) or [Promote API](https://userguide.qualytics.io/operations/promote/api/)).

All endpoints use the base URL of your Qualytics deployment (for example, `https://your-instance.qualytics.io/api`).

> **Tip**
>
> For complete API documentation, including request and response schemas, visit the [API docs](https://userguide.qualytics.io/api/docs).

## Listing Runs

Send `GET /api/operations` to retrieve a paginated list of Runs across all operation types. The endpoint supports rich filtering and sorting via query parameters.

| Query parameter | Type | Description |
| --- | --- | --- |
| `id` | integer | Filter by a specific Run ID. |
| `schedule_id` | integer | Filter by the schedule that triggered the Runs. |
| `operation_type` | string | One of `sync`, `profile`, `scan`, `external_scan`, `export`, `materialize`, `promote`. The legacy value `catalog` is no longer accepted and fails with a validation error. |
| `finished` | boolean | `true` returns only finished Runs; `false` returns only in-progress. |
| `result` | list of strings | Accepted values: `queued`, `running`, `success`, `failure`, `aborted`. Repeat the parameter to pass multiple. |
| `created_date`, `start_date`, `end_date` | date (`YYYY-MM-DD`) | Filter by the Run's creation, start, or end date. |
| `datastore` | list of integers | Filter by datastore ID. Repeat to pass multiple. |
| `container` | list of integers | Filter by container ID. Repeat to pass multiple. |
| `has_logs` | boolean | `true` returns only Runs that produced log entries; `false` returns only Runs that produced none. |
| `filters` | `string` (JSON) | Narrows the list by one or more filters, written as a JSON object. See [Filtering Lists](https://userguide.qualytics.io/operations/runs/api/#filtering-lists). |
| `offset` | integer | Timezone offset in minutes (used to align date filters with the caller's timezone). |
| `sort_created` | `asc` or `desc` | Sort the result by `created_date`. |
| `sort_duration` | `asc` or `desc` | Sort the result by `duration`. |

> **Example: List recent Scan Runs in terminal states**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/operations?operation_type=scan&result=success&result=failure&sort_created=desc" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response** (abbreviated):
>
> ```json
> {
>   "items": [
>     {
>       "id": 53388,
>       "type": "scan",
>       "created": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
>       "start_time": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
>       "end_time": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
>       "result": "success",
>       "message": null,
>       "triggered_by": "user@example.com",
>       "datastore": { "id": 101, "name": "Datastore-Sample" },
>       "status": {
>         "total_containers": 14,
>         "containers_analyzed": 14,
>         "partitions_scanned": 42,
>         "records_processed": 700000,
>         "anomalies_identified": 0
>       }
>     }
>   ],
>   "total": 1,
>   "page": 1,
>   "size": 50,
>   "pages": 1
> }
> ```

### Filtering Lists

`GET /api/operations` accepts a `filters` parameter: a JSON object with one entry per filter, saying how that filter's values should match.

```bash
curl -G "https://your-instance.qualytics.io/api/operations" \
  --data-urlencode 'filters={"result":{"not_in":["success"]}}' \
  -H "Authorization: Bearer YOUR_TOKEN"
```

This returns the Runs that didn't succeed.

| Key | Returns |
| --- | --- |
| `in` | The items that match at least one of the values. |
| `not_in` | The items that match none of the values. |
| `all_of` | The items that match every value, on filters an item can have several of, such as tags. |
| `empty` | The items with no value (`true`) or at least one (`false`), on filters an item can lack. |

- Different filters combine with AND, and so do keys on the same filter.
- `empty` can't be combined with other keys on the same filter.
- A filter sent both as its own parameter and inside `filters` returns a `422`. Put all of that filter's conditions in `filters`.
- `in`, `not_in` and `all_of` each take between 1 and 20 values.
- A filter or key the endpoint doesn't accept returns a `422` that names it. The [API docs](https://userguide.qualytics.io/api/docs) list what each endpoint accepts.

## Retrieving a Run

Send `GET /api/operations/{id}` to return the full detail payload for a single Run, including the configuration it used, the summary metrics, and the triggering metadata.

For the full shape of the response object (including operation-specific fields such as `auto_resolved_anomaly_count` on Scan Runs), see the response example in [Scan API: Retrieving Scan operation information](https://userguide.qualytics.io/operations/scan/api/#retrieving-scan-operation-information).

> **Example: Fetch a single Run by ID**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/operations/53388" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```

## Listing containers in a Run

Send `GET /api/operations/{id}/containers` to return the per-container breakdown of a Run, one entry per container the Run targeted. Each entry is the container itself (`id`, `name`, `container_type`, and the other container fields) plus the Run's result for it: `container_scan` for a Scan Run, or `container_profile` for a Profile Run. The list is paginated with `total`, `page`, `size`, and `pages`. Most useful for Profile and Scan Runs that track progress at the container level.

> **Example: List containers processed in a Scan Run**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/operations/53388/containers" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response** (abbreviated):
>
> ```json
> {
>   "items": [
>     {
>       "id": 234,
>       "name": "customers",
>       "container_type": "table",
>       "container_scan": {
>         "operation_id": 53388,
>         "start_time": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
>         "end_time": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
>         "records_processed": 50000,
>         "anomaly_count": 0,
>         "passed_checks_count": 12,
>         "failed_checks_count": 0,
>         "result": "success",
>         "message": null
>       },
>       "container_profile": null
>     }
>   ],
>   "total": 14,
>   "page": 1,
>   "size": 50,
>   "pages": 1
> }
> ```
>
> For a Profile Run, `container_profile` carries `records_count`, `records_processed`, `checks_synchronized`, `result`, and `message` instead.

## Aborting a Run

Send `PUT /api/operations/abort/{id}` to stop an in-progress Run. The Run transitions to **Aborted** as soon as the operation can stop safely, and partial results captured up to the stop point are preserved. Aborting a Run that already finished changes nothing: the request returns `200` with the Run as it was.

**Permission**: Editor team permission on the target datastore.

> **Example: Abort an in-flight Run**
>
> **Request**:
>
> ```bash
> curl -X PUT "https://your-instance.qualytics.io/api/operations/abort/53388" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response** (abbreviated): the endpoint returns the updated Run with `result` set to `aborted` and `end_time` populated.

## Resuming a Run

Send `PUT /api/operations/run/{id}` to continue an Aborted or Failure Run from the unprocessed containers (or partitions). Containers already completed in the original Run are not re-read.

Supported by Profile, Scan, and Promote. Not supported by Sync, External Scan, Export, or Materialize.

**Permission**: Editor team permission on the target datastore.

| Query parameter | Type | Description |
| --- | --- | --- |
| `force_abort` | boolean | When `true`, forces the current operation to abort before resuming. Default `false`. |

> **Example: Resume a Run from where it stopped**
>
> **Request**:
>
> ```bash
> curl -X PUT "https://your-instance.qualytics.io/api/operations/run/53204" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response** (abbreviated): the endpoint returns the updated Run with `result` set back to `running` (or briefly `queued`) and the new dispatch timestamp.

## Rerunning a Run

Send `PUT /api/operations/rerun/{id}` to start a brand-new Run that reuses the configuration of an existing Run. Every container is processed from scratch, regardless of whether it succeeded before.

Supported by Sync, Profile, Scan, Export, Materialize, and Promote. Not supported by External Scan.

**Permission**: Editor team permission on the target datastore.

> **Example: Rerun a finished Run with the same configuration**
>
> **Request**:
>
> ```bash
> curl -X PUT "https://your-instance.qualytics.io/api/operations/rerun/53388" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response** (abbreviated): the endpoint returns the **new** Run created from the original's configuration, with a fresh `id`, `created` timestamp, and `result` set to `queued` or `running`.

## Deleting a Run

Send `DELETE /api/operations/{id}` to remove the Run record (and its summary metrics) from the Activity list. Deleting a Scan or External Scan also permanently deletes the anomalies it found, recalculates quality scores, and makes the previous successful scan the latest one when the deleted Run was the latest. Deleting a Profile removes its profile results and, when it was the latest profile, makes the previous successful profile the latest one. Data written by Sync, Export, Materialize, and Promote stays in place.

**Permission**: Editor team permission on the target datastore. You must also have started the Run, unless you have the Admin role.

> **Example: Delete a Run record from the Activity list**
>
> **Request**:
>
> ```bash
> curl -X DELETE "https://your-instance.qualytics.io/api/operations/53388" \
>   -H "Authorization: Bearer YOUR_API_TOKEN"
> ```
>
> **Response**: `204 No Content` on success.

## Error Responses

| Status Code | Description |
| --- | --- |
| `400 Bad Request` | The payload is malformed or the `id` path parameter is invalid. |
| `401 Unauthorized` | Missing or invalid API token. |
| `403 Forbidden` | The user does not have the required team permission on the datastore. |
| `404 Not Found` | A Run with the specified ID does not exist. |
| `409 Conflict` | The Run is not in a state that supports the action (for example, Resume on a Run type that does not support it). |
| `422 Unprocessable Entity` | A query parameter or payload value fails schema validation. |

*Last updated: October 28, 2026.*
