# Manage check templates

Source: https://userguide.qualytics.io/cli/examples/manage-check-templates/

## Goal

Treat a curated set of quality checks as reusable templates that can be applied across many containers or datastores. Templates are how teams enforce "every PII column must have these checks" or "every transactional table must have a `freshness` check" without copy-pasting check definitions everywhere.

## Permissions

| Step | Endpoint | Role | Team permission |
| --- | --- | --- | --- |
| Export templates to a file | `GET /api/quality-checks?template_only=true` | `Member` | N/A |
| Export templates to an enrichment datastore | `POST /api/operations/run` (`global_export`) | `Manager` | N/A |
| Import templates (create) | `POST /api/quality-check-templates` | `Manager` | N/A |

> **Warning: Template management is Manager -only**
>
> Creating templates and exporting them to an enrichment datastore require the `Manager` role. Users with the `Member` role can only list templates and export them to a file.

## Prerequisites

- The CLI is installed and authenticated with a `Manager` token.
- Optionally, an enrichment datastore if you want to export templates as data records rather than to a local file.

## CLI workflow

```mermaid
graph LR
    Export[checks export-templates] --> File[templates.yaml]
    File --> Review[Review / edit]
    Review --> Import[checks import-templates]
    Import --> Templates[(Templates in target instance)]
```

### 1. Export templates from the source instance

```bash
# To a local YAML file
qualytics checks export-templates --output ./templates/golden.yaml

# Filter by rule types and tags
qualytics checks export-templates \
    --output ./templates/pii.yaml \
    --rules "isNotNull,matchesPattern" \
    --tags "pii"
```

### 2. (Optional) Edit the file

The exported YAML is a list of templates with their full definitions. You can hand-edit them before importing. The import reads only `description`, `rule_type`, `coverage`, `filter`, `properties`, the names in `global_tags`, `template_locked`, `additional_metadata`, and `anomaly_message_field`. It also reads `id`, but only to record the source template in the new template's metadata (see the next step); the new template gets its own id. Keep `id` when you edit the file. Every other field, such as `created`, is ignored.

### 3. Import templates to the target instance

```bash
qualytics checks import-templates --input ./templates/pii.yaml
```

Each template in the file becomes a new template. The CLI records the source template's id in its `additional_metadata`, under `from quality check id`.

## Behind the scenes

| CLI step | Method | Path | Notes |
| --- | --- | --- | --- |
| `checks export-templates` | GET | `/api/quality-checks?template_only=true` | Paginated (100 per page); the CLI walks all pages. `--status`, `--rules`, and `--tags` become the `template_locked`, `rule_type`, and `tag` query parameters. |
| `checks export-templates --enrichment_datastore_id` | POST | `/api/export/check-templates?enrich_datastore_id=<id>` | Writes templates as records to the selected enrichment datastore. This endpoint is deprecated; to make the same export from your own code, use `POST /api/operations/run` (see [Export to an enrichment datastore](https://userguide.qualytics.io/cli/examples/manage-check-templates/#export-to-an-enrichment-datastore-for-downstream-analytics)). |
| `checks import-templates` | POST | `/api/quality-check-templates` | One call per template in the file. **Create-only**: existing templates are not updated. |

## Python equivalent

```python
import os
import yaml
import httpx

BASE_URL = os.environ["QUALYTICS_URL"].rstrip("/")
TOKEN    = os.environ["QUALYTICS_TOKEN"]
HEADERS  = {"Authorization": f"Bearer {TOKEN}"}

PAGE_SIZE = 100
CREATE_FIELDS = (
    "description", "coverage", "filter", "properties",
    "template_locked", "additional_metadata", "anomaly_message_field",
)

with httpx.Client(headers=HEADERS, timeout=30.0) as client:
    # Export: templates are listed as quality checks with template_only=true
    templates, page = [], 1
    while True:
        r = client.get(
            f"{BASE_URL}/api/quality-checks",
            params={"template_only": "true", "size": PAGE_SIZE, "page": page},
        )
        r.raise_for_status()
        body = r.json()
        templates.extend(body["items"])
        if page * PAGE_SIZE >= body["total"]:
            break
        page += 1
    with open("./templates/golden.yaml", "w") as f:
        yaml.safe_dump(templates, f, sort_keys=False)

    # Import (create-only): build a clean create body for each template,
    # leaving out read-only fields such as id and created
    with open("./templates/golden.yaml") as f:
        for tpl in yaml.safe_load(f):
            payload = {k: tpl[k] for k in CREATE_FIELDS if tpl.get(k) is not None}
            payload["rule"] = tpl["rule_type"]
            payload["tags"] = [t["name"] for t in tpl.get("global_tags") or []]
            r = client.post(f"{BASE_URL}/api/quality-check-templates", json=payload)
            r.raise_for_status()
            print(f"created template {r.json()['id']} from {tpl['id']}")
```

## Variations and advanced usage

### Lock a template

In the web app, a template can be locked. Checks created from a locked template stay in sync with it, and their properties can't be changed directly. Useful for compliance-mandated rule sets. Filter the export by locked status:

```bash
qualytics checks export-templates --status true   # locked templates only
qualytics checks export-templates --status false  # unlocked only
```

### Export to an enrichment datastore for downstream analytics

```bash
qualytics checks export-templates --enrichment_datastore_id 10
```

The templates are written as records into the selected enrichment datastore. This is useful when you want to track template usage and changes as part of your data pipeline. Add `--check_templates "1,2,3"` to export only those template ids.

To run the same export from your own code, start a `global_export` operation:

```python
with httpx.Client(headers=HEADERS, timeout=30.0) as client:
    r = client.post(
        f"{BASE_URL}/api/operations/run",
        json={
            "type": "global_export",
            "asset_type": "check_templates",
            "enrichment_datastore_id": 10,
            "template_ids": [1, 2, 3],  # optional; leave out to export every template
        },
    )
    r.raise_for_status()
```

### Apply a template to many containers in one operation

This is a web-app-only operation today (apply-template-to-multiple-containers). See [Apply Check Template](https://userguide.qualytics.io/data-quality-checks/templates/how-tos/add-a-check/).

## Troubleshooting

| Symptom | Likely cause | Fix |
| --- | --- | --- |
| `import-templates` reports 0 created | Every template in the file failed to create, for example because its rule type is not enabled on the target instance | Read the `errors-<date>.log` file the CLI writes to its configuration folder, fix the templates, and import again. |
| The same template appears twice after an import | Imports are create-only and don't check for existing templates, so importing a file again creates every template again | Import each file once, and delete the extra copies in the web app. |
| 403 on `import-templates` or on an enrichment export | Token has `Member` role | Use a `Manager` or `Admin` token. |
| Template references a rule type the target instance doesn't support | Different Qualytics versions between source and target | Upgrade the target instance, or remove unsupported templates from the YAML. |
| Imported template doesn't appear in the web app | UI cache | Refresh the page; templates list updates immediately on import. |

## Related

- [Quality Checks command reference](https://userguide.qualytics.io/cli/quality-checks/): `export-templates` and `import-templates` flags.
- [Apply Check Template for Quality Checks](https://userguide.qualytics.io/data-quality-checks/templates/how-tos/add-a-check/): the web-app side of templates.
- [Bulk-create quality checks](https://userguide.qualytics.io/cli/examples/bulk-create-quality-checks/): create regular (non-template) checks from YAML.

*Last updated: November 10, 2026.*
