Metric Check API¶
This page documents how to create and manage a Metric check via the REST API. The check uses the standard Quality Checks endpoints: set rule to metric, name the measured field in fields, and configure the comparison under properties. All endpoints share the base URL of your deployment (for example, https://your-instance.qualytics.io/api) and require a Bearer token.
Tip
For complete API documentation, including request and response schemas, visit the API docs.
Permissions
All endpoints require the Member role plus a team permission on the check's datastore: Reporter to read, Author to create or update an Active check, archive, or delete, and Drafter to create or update a Draft. See Permissions for the full matrix.
The properties object¶
Metric carries its rule-specific configuration under properties:
| Field | Required | Type | Description |
|---|---|---|---|
comparison |
Yes | string |
"Absolute Value", "Absolute Change", or "Percentage Change". See Comparisons. |
min |
One of min / max |
number |
The lower limit. A value of the field for Absolute Value, a movement for Absolute Change, or a decimal fraction for Percentage Change (-0.2 means a 20% decrease). |
max |
One of min / max |
number |
The upper limit, in the same unit as min. |
At least one of min and max is required, and min cannot be greater than max. Either violation returns 422. Percentage Change limits are decimals in the API, while the app takes them in percent.
Create¶
Endpoint: POST /api/quality-checks
Permission: Member role + Author team permission on the container's datastore (Drafter when status is "Draft").
Create a Metric check (every accepted field)
curl -X POST "https://your-instance.qualytics.io/api/quality-checks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "EMEA conversion rate stays between 2% and 8%.",
"rule": "metric",
"fields": ["conversion_rate"],
"container_id": 655,
"filter": "region = '\''EMEA'\''",
"properties": {"comparison": "Absolute Value", "min": 0.02, "max": 0.08},
"tags": ["sales", "emea"],
"additional_metadata": {"dashboard": "https://bi.example.com/emea-funnel"},
"template_id": null,
"status": "Active",
"owner_id": 7,
"default_anomaly_assignee_id": 12,
"anomaly_message_field": null
}'
Field notes¶
| Field | Required | Notes |
|---|---|---|
description |
Yes | Free-text description shown in the UI. |
rule |
Yes | Must be "metric". |
fields |
Yes | Exactly one field name, of type Integral or Fractional. Locked after the first Scan that includes the check. |
container_id |
Yes | ID of the container (table or file) the check runs against. |
filter |
No | A SQL WHERE expression applied before the evaluation. For a Metric check it usually narrows the container to one row. |
properties |
Yes | Object holding the comparison and the limits. See above. |
tags |
No | List of tag names applied to the check. Anomalies the check produces inherit them. |
additional_metadata |
No | Free-form key-value pairs (typically links to catalog entries, tickets, governance records). |
template_id |
No | ID of a Check Template whose rule type is Metric. The template then controls the check's properties. Send null or omit it to configure the check directly. |
status |
No | "Active" (default) or "Draft". Draft checks are not evaluated by Scans. |
owner_id |
No | ID of the user who owns the check. Defaults to the user creating the check when omitted. |
default_anomaly_assignee_id |
No | ID of the user automatically assigned to anomalies produced by the check. |
anomaly_message_field |
No | Name of a field on the same row whose value replaces the default anomaly message. Send null or omit it for the default message. |
coverage is not supported. The rule evaluates one row, so there is no share of passing rows to tolerate. Any value other than 1 is rejected with 422.
Read¶
Endpoint: GET /api/quality-checks/{id}
Permission: Member role + Reporter team permission on the check's datastore.
Retrieve a check by ID
The response's last_asserted field is empty until a Scan has asserted the check.
Measurements¶
Endpoint: GET /api/quality-checks/{id}/measurements
Returns the check together with its most recent measurements (up to 11), newest first. Each measurement carries its created time and its value. The endpoint returns 409 for a check that is not a Metric check. To list several Metric checks with their measurements, see List Metric measurements.
Retrieve a check's measurements
Update¶
Endpoint: PUT /api/quality-checks/{id}
Permission: Member role + Author team permission on the check's datastore (Drafter when the check stays Draft).
Every PUT requires description and the full properties object, including comparison and at least one of min or max. Repeat the check's current properties even when changing only its description, tags, or other metadata: a request without them returns 422. Partial property updates are not merged.
Widen the limits
curl -X PUT "https://your-instance.qualytics.io/api/quality-checks/101" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "EMEA conversion rate stays between 1.5% and 9%.",
"properties": {"comparison": "Absolute Value", "min": 0.015, "max": 0.09}
}'
A PUT can update most fields on an existing Metric check. Three values stay immutable: the rule type, the container the check is attached to, and template_id. Once a Scan has included the check, the field and the comparison become immutable too: changing fields returns 400, and sending a different comparison returns 409.
Editable vs Immutable on PUT
Editable
descriptionfilterproperties.minproperties.maxfields(only until the first Scan that includes the check)properties.comparison(only until the first Scan that includes the check)tagsadditional_metadatastatusowner_iddefault_anomaly_assignee_idanomaly_message_field
Immutable
rulecontainer_idtemplate_id
Delete¶
Endpoint: DELETE /api/quality-checks/{id}
Permission: Member role + Author team permission on the check's datastore.
Three query parameters control what happens, mirroring the two-stage flow in the UI:
| Parameter | Default | Description |
|---|---|---|
archive |
true |
When true, the check is archived and can be restored later. When false, the check is permanently deleted. |
status |
Discarded |
The archive resolution: Discarded (no longer relevant) or Invalid (wrong and suppressed from future AI generation). Only used when archive=true. |
delete_anomalies |
true |
Whether to permanently delete the anomalies the check produced. A permanent delete (archive=false) always removes them. |
Archive a check, keeping its anomalies
Delete a check permanently
Error responses¶
| Status | Description |
|---|---|
400 Bad Request |
A business-logic conflict prevents the operation (for example, changing the fields of a check that a Scan has already included, changing properties while the check is archived, or switching an archived check between Discarded and Invalid). |
401 Unauthorized |
Missing or invalid API token. |
403 Forbidden |
The caller lacks the required team permission on the check's datastore. |
404 Not Found |
The check ID does not exist. |
409 Conflict |
An Active Metric check with the same field, filter, and comparison already exists on the container, or a PUT tried to change the comparison of a check that a Scan has already included. |
422 Unprocessable Entity |
The payload fails schema validation (for example, description missing on PUT, neither min nor max set, min greater than max, or a coverage other than 1). |