Aggregation Comparison Check API
This page documents how to create and manage an Aggregation Comparison check via the REST API. The check uses the standard Quality Checks endpoints: set rule to aggregationComparison and provide both aggregation expressions plus the comparison operator under properties. The rule evaluates one aggregate per side, so the fields array is not used. 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
Aggregation Comparison carries all of its rule-specific configuration under properties:
| Field | Required | Type | Description |
|---|---|---|---|
expression |
Yes | string |
The target aggregation, evaluated against container_id. Must produce a single aggregate value. Accepts Check Variables. |
comparison |
Yes | string |
The operator applied as target <op> reference: lt, lte, eq, gte, or gt. Shown in the UI as Less Than, Less Than Or Equal To, Equal To, Greater Than Or Equal To, and Greater Than. |
ref_datastore_id |
No | int |
Datastore holding the reference container. Omit or send null when it lives in the same datastore as the target. |
ref_container_id |
Yes | int |
The reference container. Can be the same as container_id. |
ref_expression |
Yes | string |
The reference aggregation. Must also produce a single aggregate value. Accepts Check Variables. |
ref_filter |
No | string |
SQL WHERE expression applied to the reference container before its aggregation runs. Accepts Check Variables. |
Create
Endpoint: POST /api/quality-checks
Permission: Member role + Author team permission on the container's datastore (Drafter when status is "Draft").
Create an Aggregation Comparison 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": "Order totals must equal the line-item roll-up.",
"rule": "aggregationComparison",
"fields": [],
"container_id": 145,
"filter": null,
"properties": {
"expression": "ROUND(SUM(o_totalprice))",
"comparison": "eq",
"ref_container_id": 178,
"ref_expression": "ROUND(SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)))",
"ref_filter": null
},
"tags": ["reconciliation", "finance"],
"additional_metadata": {"jira": "DATA-4012"},
"template_id": null,
"status": "Active",
"owner_id": 7,
"default_anomaly_assignee_id": 12
}'
To reference a container in a different datastore, add ref_datastore_id inside properties.
Field notes
| Field | Required | Notes |
|---|---|---|
description |
Yes | Free-text description shown in the UI. |
rule |
Yes | Must be "aggregationComparison". |
fields |
No | Aggregation Comparison does not select columns. Send an empty array [] or omit. |
container_id |
Yes | ID of the target container (table or file) the check runs against. |
filter |
No | SQL WHERE expression applied to the target container before the target aggregation runs. Send null for no filter. |
properties |
Yes | Object holding the rule-specific configuration. See above. |
tags |
No | List of tag names applied to the check for filtering and organization. |
additional_metadata |
No | Free-form key-value pairs (typically links to catalog entries, tickets, governance records). |
template_id |
No | ID of a Check Template to associate the check with. null if not using a template. |
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. |
Two payload fields exist for other rule types but do not apply here:
coverageis ignored. The rule asserts a single boolean condition between two aggregates and has no per-row violation rate.anomaly_message_fieldis ignored. Aggregation Comparison emits Shape Anomalies only, and Shape Anomalies always use the fixed message.
Read
Endpoint: GET /api/quality-checks/{id}
Permission: Member role + Reporter team permission on the check's datastore.
Retrieve a check by ID
Update
Endpoint: PUT /api/quality-checks/{id}
Permission: Member role + Author team permission on the check's datastore (Drafter when the check stays Draft).
The PUT endpoint requires description; include the check's current description (or a new one) along with the fields you want to change. Send the whole properties object: partial property updates are not merged.
Switch the operator and rewrite the reference aggregation
curl -X PUT "https://your-instance.qualytics.io/api/quality-checks/101" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Order totals must not exceed the line-item roll-up.",
"properties": {
"expression": "ROUND(SUM(o_totalprice))",
"comparison": "lte",
"ref_container_id": 178,
"ref_expression": "ROUND(SUM(l_extendedprice))",
"ref_filter": "l_shipdate >= current_date() - INTERVAL 1 DAY"
}
}'
A PUT can update most fields on an existing Aggregation Comparison check. Three values stay immutable: the rule type, the target container the check is attached to, and the associated Check Template. If any of these needs to change, delete the check and create a new one. The reference container is not immutable: it is part of properties and can be repointed.
Editable vs Immutable on PUT
Editable
descriptionfilterproperties.expressionproperties.comparisonproperties.ref_datastore_idproperties.ref_container_idproperties.ref_expressionproperties.ref_filtertagsadditional_metadatastatusowner_iddefault_anomaly_assignee_id
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 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, or on the reference container's datastore. |
404 Not Found |
The check ID, the reference datastore, or the reference container does not exist. |
422 Unprocessable Entity |
The payload fails schema validation (for example, description missing on PUT, an unknown comparison value, or a missing ref_expression). |