# Promote API

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

This page documents the API endpoints for running promote operations and viewing their results. Use these endpoints to programmatically promote quality checks, computed fields, computed tables, and computed files across your Qualytics deployment.

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

> **Tip: Interactive API reference**
>
> For the full, interactive API reference, including request schemas, response examples, and an in-browser request runner, visit the [API docs](https://userguide.qualytics.io/api/docs).

## Run a Promote Operation

All promote operations use the same endpoint, distinguished by the `type` field in the request body. The operation runs asynchronously, so you receive an operation ID immediately and can poll for results.

**Endpoint**: `POST /api/operations/run`

**Permission**: **Editor** team permission on both the source and the destination. This applies to every promote type. See [Permissions](https://userguide.qualytics.io/operations/promote/deep-dive/permissions/) for details.

---

### Promote Quality Checks

Promotes quality check definitions from one container to another.

**Request Body**:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | string | Yes | - | Must be `promote_quality_check` |
| `datastore_id` | integer | Yes | - | The source datastore ID |
| `container_id` | integer | Yes | - | The source container ID |
| `destination_container_id` | integer | Yes | - | The destination container ID |
| `check_ids` | `list[integer]` | No | - | Specific quality check IDs to promote. Mutually exclusive with `check_tags` |
| `check_tags` | `list[string]` | No | - | Tags to filter quality checks for promotion. Mutually exclusive with `check_ids` |
| `check_additional_tags` | `list[string]` | No | - | Tags to add to promoted checks at the destination |
| `as_draft` | boolean | No | `true` | When `true`, promoted checks are created as Draft. When `false`, new checks are validated and created as Active |

> **Note**
>
> If neither `check_ids` nor `check_tags` is specified, all Active and Draft quality checks on the source container are promoted. Checks in `Archived` or `Discarded` status are always excluded, even when listed explicitly by ID.

> **Info: Active validation runs in batches of 10**
>
> When `as_draft` is `false`, the platform validates each new destination check against the destination container before persisting it. Validation runs in **batches of 10**, with one round trip to the Dataplane per batch. If a check fails validation (or the batch errors out), the just-created destination row is removed and the source check is recorded as `failed` for that batch, so no orphan check is left behind. Active promotions of thousands of checks proceed in many such batches; promotion time scales linearly with the number of validation batches.

> **Example: Example request**
>
> ```bash
> curl -X POST "https://your-instance.qualytics.io/api/operations/run" \
>   -H "Authorization: Bearer YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "type": "promote_quality_check",
>     "datastore_id": 1,
>     "container_id": 10,
>     "destination_container_id": 20,
>     "check_tags": ["pii-checks"],
>     "check_additional_tags": ["promoted-from-staging"],
>     "as_draft": true
>   }'
> ```

---

### Promote Computed Fields

Promotes computed field definitions from one container to another.

**Request Body**:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | string | Yes | - | Must be `promote_computed_field` |
| `datastore_id` | integer | Yes | - | The source datastore ID |
| `container_id` | integer | Yes | - | The source container ID |
| `destination_container_id` | integer | Yes | - | The destination container ID |
| `computed_field_ids` | `list[integer]` | No | - | Specific computed field IDs to promote. Mutually exclusive with `computed_field_tags` |
| `computed_field_tags` | `list[string]` | No | - | Tags to filter computed fields for promotion. Mutually exclusive with `computed_field_ids` |
| `computed_field_additional_tags` | `list[string]` | No | - | Tags to add to promoted computed fields at the destination |

> **Note**
>
> If neither `computed_field_ids` nor `computed_field_tags` is specified, all computed fields on the source container are promoted.

> **Example: Example request**
>
> ```bash
> curl -X POST "https://your-instance.qualytics.io/api/operations/run" \
>   -H "Authorization: Bearer YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "type": "promote_computed_field",
>     "datastore_id": 1,
>     "container_id": 10,
>     "destination_container_id": 30,
>     "computed_field_ids": [101, 102, 103]
>   }'
> ```

---

### Promote Computed Tables

Promotes computed table definitions from one JDBC datastore to another.

**Request Body**:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | string | Yes | - | Must be `promote_computed_table` |
| `datastore_id` | integer | Yes | - | The source datastore ID |
| `destination_datastore_id` | integer | Yes | - | The destination JDBC datastore ID |
| `container_ids` | `list[integer]` | No | - | Specific computed table container IDs to promote. Mutually exclusive with `container_tags` |
| `container_tags` | `list[string]` | No | - | Tags to filter computed tables for promotion. Mutually exclusive with `container_ids` |
| `container_additional_tags` | `list[string]` | No | - | Tags to add to promoted computed tables at the destination |

> **Note**
>
> If neither `container_ids` nor `container_tags` is specified, all computed tables on the source datastore are promoted.

> **Example: Example request**
>
> ```bash
> curl -X POST "https://your-instance.qualytics.io/api/operations/run" \
>   -H "Authorization: Bearer YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "type": "promote_computed_table",
>     "datastore_id": 1,
>     "destination_datastore_id": 2,
>     "container_tags": ["analytics"],
>     "container_additional_tags": ["promoted"]
>   }'
> ```

---

### Promote Computed Files

Promotes computed file definitions from one DFS datastore to another, with explicit file pattern mapping.

**Request Body**:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | string | Yes | - | Must be `promote_computed_file` |
| `datastore_id` | integer | Yes | - | The source datastore ID |
| `destination_datastore_id` | integer | Yes | - | The destination DFS datastore ID |
| `source_container_mappings` | `list[object]` | Yes | - | Mapping of each source computed file to a destination file pattern (see below) |
| `container_additional_tags` | `list[string]` | No | - | Tags to add to promoted computed files at the destination |

**`source_container_mappings` object**:

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `container_id` | integer | Yes | The source computed file container ID |
| `destination_container_id` | integer | Yes | The destination file pattern container ID on the destination datastore |

> **Example: Example request**
>
> ```bash
> curl -X POST "https://your-instance.qualytics.io/api/operations/run" \
>   -H "Authorization: Bearer YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "type": "promote_computed_file",
>     "datastore_id": 1,
>     "destination_datastore_id": 3,
>     "source_container_mappings": [
>       { "container_id": 50, "destination_container_id": 60 },
>       { "container_id": 51, "destination_container_id": 61 }
>     ],
>     "container_additional_tags": ["promoted"]
>   }'
> ```

---

## View Promote Operation Results

### Get Operation Details

Retrieves the full details of a promote operation, including per-entity results.

**Endpoint**: `GET /api/operations/{id}`

**Path Parameters**:

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | Yes | The operation ID |

> **Example: Example request and response**
>
> **Request**:
>
> ```bash
> curl -X GET "https://your-instance.qualytics.io/api/operations/500" \
>   -H "Authorization: Bearer YOUR_TOKEN"
> ```
>
> **Response** (abbreviated):
>
> ```json
> {
>   "id": 500,
>   "type": "promote",
>   "promote_type": "quality_check",
>   "result": "success",
>   "start_time": "2026-03-10T14:30:00Z",
>   "end_time": "2026-03-10T14:30:15Z",
>   "triggered_by": "jane@example.com",
>   "datastore": { "id": 1, "name": "Staging Warehouse" },
>   "destination_datastore": { "id": 2, "name": "Production Warehouse" },
>   "container": { "id": 10, "name": "orders" },
>   "destination_container": { "id": 20, "name": "orders" },
>   "as_draft": true,
>   "status": {
>     "total": 5,
>     "created": 3,
>     "updated": 1,
>     "skipped": 1,
>     "failed": 0
>   },
>   "results": [
>     {
>       "source_entity_id": 101,
>       "source_entity": {
>         "id": 101,
>         "description": "Email format validation",
>         "rule_type": "matches_pattern",
>         "status": "active"
>       },
>       "entity_type": "quality_check",
>       "result": "created",
>       "destination_entity_id": 201,
>       "destination_entity": {
>         "id": 201,
>         "description": "Email format validation",
>         "rule_type": "matches_pattern",
>         "status": "draft"
>       },
>       "message": null
>     }
>   ]
> }
> ```

---

### Filter Promote Results

You can filter the entities in a promote operation by their result status using dedicated sub-endpoints.

#### Quality Check Results

**Endpoint**: `GET /api/operations/{id}/quality-checks`

**Query Parameters**:

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | No | Filter by check description or rule type |
| `promote_result` | `list[string]` | No | Filter by result: `created`, `updated`, `skipped`, `failed` |

#### Computed Field Results

**Endpoint**: `GET /api/operations/{id}/fields`

**Query Parameters**:

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | No | Filter by field name |
| `promote_result` | `list[string]` | No | Filter by result: `created`, `updated`, `skipped`, `failed` |

#### Computed Table / File Results

**Endpoint**: `GET /api/operations/{id}/containers`

**Query Parameters**:

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `search` | string | No | Filter by container name |
| `promote_result` | `list[string]` | No | Filter by result: `created`, `updated`, `skipped`, `failed` |

---

## Response Schema Reference

### Promote Operation Fields

The operation envelope includes a few promote-specific fields alongside the standard operation shape:

| Property | Type | Description |
| --- | --- | --- |
| `type` | string | Always `promote` for promote operations |
| `promote_type` | string | Identifies which entity type was promoted. One of: `quality_check`, `computed_field`, `computed_table`, `computed_file` |
| `as_draft` | boolean | Present only on `quality_check` promotions; shows the request setting |

### Promote Status

Every promote operation response includes a `status` object summarizing the results:

| Property | Type | Description |
| --- | --- | --- |
| `total` | integer | Total number of entities in the operation |
| `created` | integer | Number of new entities created at the destination |
| `updated` | integer | Number of existing entities updated at the destination |
| `skipped` | integer | Number of entities skipped (definition identical to destination) |
| `failed` | integer | Number of entities that failed to promote |

### Promote Result (Per Entity)

Each entity in the `results` array has the following structure:

| Property | Type | Description |
| --- | --- | --- |
| `source_entity_id` | integer | ID of the source entity |
| `source_entity` | object or null | Source entity details (null if deleted) |
| `entity_type` | string | One of: `quality_check`, `computed_field`, `computed_table`, `computed_file` |
| `result` | string | One of: `created`, `updated`, `skipped`, `failed` |
| `destination_entity_id` | integer or null | ID of the destination entity (if applicable) |
| `destination_entity` | object or null | Destination entity details (if applicable) |
| `message` | string or null | Additional context (e.g., error details, warnings) |

#### Common `message` values

The `message` field is `null` for clean `created`/`updated`/`skipped` outcomes. When promotion succeeds with a caveat or fails entirely, the message is filled in. Recurring examples:

| Promote Type | `result` | Example `message` |
| --- | --- | --- |
| Quality Checks | `created` / `updated` | `"Promoted as Draft: source fields ['email'] could not be resolved on the destination"` |
| Quality Checks | `failed` | `"Validation failed: field 'email' not found on destination container"` |
| Computed Fields | `failed` | `"Source field(s) ['amount_usd'] not available on destination — their parent computed field may have failed to promote"` |
| Computed Fields | `updated` | `"Reactivated non-active field on destination"` |
| Computed Tables | `failed` | `"Cannot promote over non-computed-table container (type: table)"` |
| Computed Files | `failed` | `"Cannot promote over non-computed-file container (type: file_pattern)"` |
| Any | `failed` | `"Source and destination must be different"` (request-level, surfaced as a `422` before any entity is processed) |

These messages are informational and intended for human review on the Activity page. They are not stable identifiers, so do not parse them programmatically. Use the `result` field for automation.

### Operation Result Values

| Value | Description |
| --- | --- |
| `success` | At least one entity was created, updated, or skipped |
| `failure` | All entities failed |
| `running` | The operation is still in progress |
| `aborted` | The operation was aborted from the Activity page; already-processed entities keep their result |

---

## Permission Summary

Every promote type uses the same gate: the caller must have **Editor** team permission on both the source and the destination. If either side is missing, the API returns `403 Forbidden` and the operation is not enqueued. See [Permissions](https://userguide.qualytics.io/operations/promote/deep-dive/permissions/) for the full breakdown of user roles and team permissions.

*Last updated: August 24, 2026.*
