# Create, Manage & Delete

{% hint style="info" %}
It is highly recommended to review [#monitor-validation-and-constraints](#monitor-validation-and-constraints "mention") section to understand the required payload structure for creating and updating monitors.

For practical examples, see the [Monitor Creation Examples](https://docs.decube.io/public-api/overview/index/monitors/examples) guide.
{% endhint %}

{% hint style="danger" %}
Deprecation of legacy test types Not Null, Null%, Is Unique, Unique%, Is Email and Is UUID was completed on 30 January 2026. If you had existing monitors with these types, please use the new enums of Null, Unique, Email and UUID instead. Read more [here](https://docs.decube.io/data-quality/available-monitor-types/deprecation-guide-unified-tests).
{% endhint %}

## Create Monitor

> Creates a new monitor with the provided configuration. Returns the created monitor ID.

```json
{"openapi":"3.1.0","info":{"title":"Decube Public API (BETA)","version":"1.0.0"},"servers":[{"url":"https://connect.<REGION>.decube.io/api/v1/data"}],"paths":{"/monitors":{"post":{"tags":["Monitors"],"summary":"Create Monitor","description":"Creates a new monitor with the provided configuration. Returns the created monitor ID.","operationId":"create_monitor_monitors_post","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CreateMonitorBody":{"properties":{"asset":{"anyOf":[{"$ref":"#/components/schemas/DatasetIdentifier"},{"$ref":"#/components/schemas/PropertyIdentifier"},{"$ref":"#/components/schemas/SourceIdentifier"}],"title":"Asset"},"test_type":{"type":"string","enum":["volume","custom_sql","freshness","null_percentage","not_null","is_unique","unique_percentage","cardinality","avg","min","max","sum","range","string_length","is_email","is_uuid","regex_match","value_in","value_is","is_past_date","is_future_date","zero_percentage","negative_percentage","null","unique","email","uuid"],"title":"Test Type"},"mode":{"$ref":"#/components/schemas/MonitorMode"},"name":{"type":"string","maxLength":100,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"},"notify":{"type":"boolean","title":"Notify"},"custom_alerts":{"anyOf":[{"$ref":"#/components/schemas/Alert"},{"type":"null"}]},"incident_level":{"$ref":"#/components/schemas/IncidentLevel"},"dimension":{"anyOf":[{"$ref":"#/components/schemas/Dimension"},{"type":"null"}]},"row_creation":{"anyOf":[{"$ref":"#/components/schemas/SqlExpressionMode"},{"$ref":"#/components/schemas/TimestampMode"},{"$ref":"#/components/schemas/AllRecordsMode"},{"type":"null"}],"title":"Row Creation"},"frequency":{"anyOf":[{"$ref":"#/components/schemas/HourModeFrequency"},{"$ref":"#/components/schemas/DailyModeFrequency"},{"$ref":"#/components/schemas/WeeklyModeFrequency"},{"$ref":"#/components/schemas/MonthlyModeFrequency"},{"type":"null"}],"title":"Frequency"},"lookback_period":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Lookback Period"},"custom_sql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Sql"},"total_row_count_query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Total Row Count Query"},"threshold":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/AutoThreshold"},{"$ref":"#/components/schemas/PercentageRange"},{"$ref":"#/components/schemas/AbsoluteRange"},{"$ref":"#/components/schemas/PositiveRange"},{"$ref":"#/components/schemas/AnyRange"}],"discriminator":{"propertyName":"type","mapping":{"absolute":"#/components/schemas/AbsoluteRange","any_range":"#/components/schemas/AnyRange","auto":"#/components/schemas/AutoThreshold","percentage":"#/components/schemas/PercentageRange","positive_range":"#/components/schemas/PositiveRange"}}},{"type":"null"}],"title":"Threshold"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"grouping":{"anyOf":[{"$ref":"#/components/schemas/Grouping"},{"type":"null"}]}},"type":"object","required":["asset","test_type","mode","name","notify","incident_level"],"title":"CreateMonitorBody"},"DatasetIdentifier":{"properties":{"type":{"type":"string","const":"dataset","title":"Type"},"id":{"type":"integer","minimum":1,"title":"Id","description":"Unique identifier of the dataset asset"}},"type":"object","required":["type","id"],"title":"DatasetIdentifier"},"PropertyIdentifier":{"properties":{"type":{"type":"string","const":"property","title":"Type"},"id":{"type":"integer","minimum":1,"title":"Id","description":"Unique identifier of the property asset"}},"type":"object","required":["type","id"],"title":"PropertyIdentifier"},"SourceIdentifier":{"properties":{"type":{"type":"string","const":"source","title":"Type"},"id":{"type":"integer","minimum":1,"title":"Id","description":"Unique identifier of the source asset"}},"type":"object","required":["type","id"],"title":"SourceIdentifier"},"MonitorMode":{"type":"string","enum":["scheduled","on_demand"],"title":"MonitorMode"},"Alert":{"properties":{"email":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Email"},"slack":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Slack"},"teams_webhook":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Teams Webhook"}},"type":"object","title":"Alert"},"IncidentLevel":{"type":"string","enum":["info","warning","critical"],"title":"IncidentLevel"},"Dimension":{"type":"string","enum":["accuracy","completeness","consistency","timeliness","uniqueness","validity","granularity","others"],"title":"Dimension"},"SqlExpressionMode":{"properties":{"filter_mode":{"type":"string","const":"sql_expression","title":"Filter Mode"},"sql_expression":{"type":"string","title":"Sql Expression"},"enable_smart_training":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Smart Training"}},"type":"object","required":["filter_mode","sql_expression"],"title":"SqlExpressionMode"},"TimestampMode":{"properties":{"filter_mode":{"type":"string","const":"timestamp","title":"Filter Mode"},"metric_column_id":{"type":"integer","title":"Metric Column Id"},"enable_smart_training":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Smart Training"}},"type":"object","required":["filter_mode","metric_column_id"],"title":"TimestampMode"},"AllRecordsMode":{"properties":{"filter_mode":{"type":"string","const":"all_records","title":"Filter Mode"}},"type":"object","required":["filter_mode"],"title":"AllRecordsMode"},"HourModeFrequency":{"properties":{"frequency":{"type":"string","enum":["1H","3H","6H","12H"],"title":"Frequency"}},"type":"object","required":["frequency"],"title":"HourModeFrequency"},"DailyModeFrequency":{"properties":{"frequency":{"type":"string","const":"1D","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","timezone"],"title":"DailyModeFrequency"},"WeeklyModeFrequency":{"properties":{"frequency":{"type":"string","const":"7D","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"day_of_week":{"type":"integer","title":"Day Of Week"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","day_of_week","timezone"],"title":"WeeklyModeFrequency"},"MonthlyModeFrequency":{"properties":{"frequency":{"type":"string","const":"MS","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"day_of_month":{"type":"integer","title":"Day Of Month"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","day_of_month","timezone"],"title":"MonthlyModeFrequency"},"AutoThreshold":{"properties":{"type":{"type":"string","const":"auto","title":"Type"}},"type":"object","required":["type"],"title":"AutoThreshold"},"PercentageRange":{"properties":{"type":{"type":"string","const":"percentage","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"PercentageRange"},"AbsoluteRange":{"properties":{"type":{"type":"string","const":"absolute","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"AbsoluteRange"},"PositiveRange":{"properties":{"type":{"type":"string","const":"positive_range","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"PositiveRange"},"AnyRange":{"properties":{"type":{"type":"string","const":"any_range","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"AnyRange"},"Grouping":{"properties":{"group_by":{"$ref":"#/components/schemas/PropertyIdentifier"},"groups":{"items":{"type":"string"},"type":"array","title":"Groups"}},"type":"object","required":["group_by","groups"],"title":"Grouping"},"CreateMonitorResult":{"properties":{"monitor_id":{"type":"integer","title":"Monitor Id"}},"type":"object","required":["monitor_id"],"title":"CreateMonitorResult"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}
```

## Update Monitor

> Updates an existing monitor (excluding Schema Drift and Job Failure monitors). Requires full monitor configuration in the request body. Returns the updated monitor ID.

```json
{"openapi":"3.1.0","info":{"title":"Decube Public API (BETA)","version":"1.0.0"},"servers":[{"url":"https://connect.<REGION>.decube.io/api/v1/data"}],"paths":{"/monitors":{"put":{"tags":["Monitors"],"summary":"Update Monitor","description":"Updates an existing monitor (excluding Schema Drift and Job Failure monitors). Requires full monitor configuration in the request body. Returns the updated monitor ID.","operationId":"update_monitor_monitors_put","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMonitorBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"UpdateMonitorBody":{"properties":{"id":{"type":"integer","title":"Id"},"name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"},"notify":{"type":"boolean","title":"Notify"},"custom_alerts":{"anyOf":[{"$ref":"#/components/schemas/Alert"},{"type":"null"}]},"incident_level":{"$ref":"#/components/schemas/IncidentLevel"},"dimension":{"anyOf":[{"$ref":"#/components/schemas/Dimension"},{"type":"null"}]},"row_creation":{"anyOf":[{"$ref":"#/components/schemas/SqlExpressionMode"},{"$ref":"#/components/schemas/TimestampMode"},{"$ref":"#/components/schemas/AllRecordsMode"},{"type":"null"}],"title":"Row Creation"},"frequency":{"anyOf":[{"$ref":"#/components/schemas/HourModeFrequency"},{"$ref":"#/components/schemas/DailyModeFrequency"},{"$ref":"#/components/schemas/WeeklyModeFrequency"},{"$ref":"#/components/schemas/MonthlyModeFrequency"},{"type":"null"}],"title":"Frequency"},"lookback_period":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"title":"Lookback Period"},"custom_sql":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Sql"},"total_row_count_query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Total Row Count Query"},"threshold":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/AutoThreshold"},{"$ref":"#/components/schemas/PercentageRange"},{"$ref":"#/components/schemas/AbsoluteRange"},{"$ref":"#/components/schemas/PositiveRange"},{"$ref":"#/components/schemas/AnyRange"}],"discriminator":{"propertyName":"type","mapping":{"absolute":"#/components/schemas/AbsoluteRange","any_range":"#/components/schemas/AnyRange","auto":"#/components/schemas/AutoThreshold","percentage":"#/components/schemas/PercentageRange","positive_range":"#/components/schemas/PositiveRange"}}},{"type":"null"}],"title":"Threshold"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"groups":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Groups"}},"type":"object","required":["id","notify","incident_level"],"title":"UpdateMonitorBody"},"Alert":{"properties":{"email":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Email"},"slack":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Slack"},"teams_webhook":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Teams Webhook"}},"type":"object","title":"Alert"},"IncidentLevel":{"type":"string","enum":["info","warning","critical"],"title":"IncidentLevel"},"Dimension":{"type":"string","enum":["accuracy","completeness","consistency","timeliness","uniqueness","validity","granularity","others"],"title":"Dimension"},"SqlExpressionMode":{"properties":{"filter_mode":{"type":"string","const":"sql_expression","title":"Filter Mode"},"sql_expression":{"type":"string","title":"Sql Expression"},"enable_smart_training":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Smart Training"}},"type":"object","required":["filter_mode","sql_expression"],"title":"SqlExpressionMode"},"TimestampMode":{"properties":{"filter_mode":{"type":"string","const":"timestamp","title":"Filter Mode"},"metric_column_id":{"type":"integer","title":"Metric Column Id"},"enable_smart_training":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Smart Training"}},"type":"object","required":["filter_mode","metric_column_id"],"title":"TimestampMode"},"AllRecordsMode":{"properties":{"filter_mode":{"type":"string","const":"all_records","title":"Filter Mode"}},"type":"object","required":["filter_mode"],"title":"AllRecordsMode"},"HourModeFrequency":{"properties":{"frequency":{"type":"string","enum":["1H","3H","6H","12H"],"title":"Frequency"}},"type":"object","required":["frequency"],"title":"HourModeFrequency"},"DailyModeFrequency":{"properties":{"frequency":{"type":"string","const":"1D","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","timezone"],"title":"DailyModeFrequency"},"WeeklyModeFrequency":{"properties":{"frequency":{"type":"string","const":"7D","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"day_of_week":{"type":"integer","title":"Day Of Week"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","day_of_week","timezone"],"title":"WeeklyModeFrequency"},"MonthlyModeFrequency":{"properties":{"frequency":{"type":"string","const":"MS","title":"Frequency"},"time_of_day":{"type":"integer","title":"Time Of Day"},"day_of_month":{"type":"integer","title":"Day Of Month"},"timezone":{"type":"string","title":"Timezone"}},"type":"object","required":["frequency","time_of_day","day_of_month","timezone"],"title":"MonthlyModeFrequency"},"AutoThreshold":{"properties":{"type":{"type":"string","const":"auto","title":"Type"}},"type":"object","required":["type"],"title":"AutoThreshold"},"PercentageRange":{"properties":{"type":{"type":"string","const":"percentage","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"PercentageRange"},"AbsoluteRange":{"properties":{"type":{"type":"string","const":"absolute","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"AbsoluteRange"},"PositiveRange":{"properties":{"type":{"type":"string","const":"positive_range","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"PositiveRange"},"AnyRange":{"properties":{"type":{"type":"string","const":"any_range","title":"Type"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"}},"type":"object","required":["type","min","max"],"title":"AnyRange"},"CreateMonitorResult":{"properties":{"monitor_id":{"type":"integer","title":"Monitor Id"}},"type":"object","required":["monitor_id"],"title":"CreateMonitorResult"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}
```

## Delete Monitor

> Delete a monitor by ID.

```json
{"openapi":"3.1.0","info":{"title":"Decube Public API (BETA)","version":"1.0.0"},"servers":[{"url":"https://connect.<REGION>.decube.io/api/v1/data"}],"paths":{"/monitors":{"delete":{"tags":["Monitors"],"summary":"Delete Monitor","description":"Delete a monitor by ID.","operationId":"delete_monitor_monitors_delete","parameters":[{"name":"monitor_id","in":"query","required":true,"schema":{"type":"integer","minimum":1,"description":"Unique identifier of the monitor","title":"Monitor Id"},"description":"Unique identifier of the monitor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}
```

## Monitor Validation & Constraints

This section documents the request model, validation rules, and conditional requirements for creating and updating monitors. It is important to understand these rules to ensure that the monitors are created and updated correctly.

### Monitorable assets

* Allowed asset types for monitors are restricted to: Source, Dataset/Data Asset, Collection, Property/Data Asset Property, Data Job.
* The `asset` must exist and be active (not deleted) in your organization.

### Asset types by test

The following table maps monitor test types to the primary asset types they support. Use this as a quick reference when creating or updating monitors.

| Test Type    | Primary Asset Type | create\_supported |
| ------------ | ------------------ | ----------------- |
| Freshness    | dataset            | yes               |
| Volume       | dataset            | yes               |
| Field Health | property           | yes               |
| Custom SQL   | source             | yes               |
| Schema Drift | collection         | no                |
| Job Failure  | data\_job          | no                |

Note: "create\_supported" indicates whether the API supports creating a monitor of this test type. "no" means there is no create option via the monitors create endpoint for that test type; these tests are already created upon source connection and only can be updated.

### Supported test types by monitor mode

The following table shows which test types are available for each monitor mode:

| Test Type              | On-Demand Support | Scheduled Support | Notes                            |
| ---------------------- | :---------------: | :---------------: | -------------------------------- |
| Freshness              |         ✅         |         ✅         | Dataset-level monitoring         |
| Volume                 |         ✅         |         ✅         | Dataset-level monitoring         |
| **Field Health Tests** |                   |                   |                                  |
| Average                |         ✅         |         ✅         | Numeric columns only             |
| Min                    |         ✅         |         ✅         | Numeric columns only             |
| Max                    |         ✅         |         ✅         | Numeric columns only             |
| Sum                    |         ✅         |         ✅         | Numeric columns only             |
| Range                  |         ✅         |         ✅         | Numeric columns only             |
| Not Null               |         ✅         |         ✅         | All data types                   |
| Null %                 |         ✅         |         ✅         | All data types                   |
| Is Unique              |         ✅         |         ✅         | All data types                   |
| Unique %               |         ✅         |         ✅         | All data types                   |
| String Length          |         ✅         |         ✅         | String columns only              |
| Is Email               |         ✅         |         ✅         | String columns only              |
| Is UUID                |         ✅         |         ✅         | String columns only              |
| Value is               |         ✅         |         ✅         | String columns only              |
| Value in               |         ✅         |         ✅         | String columns only              |
| Regex Match            |         ✅         |         ✅         | String columns only              |
| Cardinality            |         ❌         |         ✅         | Special restrictions apply       |
| **Other Test Types**   |                   |                   |                                  |
| Custom SQL             |         ✅         |         ✅         | Custom query validation required |
| Schema Drift           |         ❌         |         ✅         | Table/Column changes only        |
| Job Failure            |         ❌         |         ✅         | Data job monitoring only         |

### Test type capabilities and features

The following table shows which features are supported for each test type across different monitor modes:

| Test Type               |  Grouping Support  | Smart Training | Quality Dimensions | Row Creation Required |
| ----------------------- | :----------------: | :------------: | :----------------: | :-------------------: |
| **Dataset-Level Tests** |                    |                |                    |                       |
| Freshness               | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Volume                  | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| **Field Health Tests**  |                    |                |                    |                       |
| Average                 | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Min                     | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Max                     | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Sum                     | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Range                   | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Not Null                | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Null %                  | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Is Unique               | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Unique %                | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| String Length           | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Is Email                | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Is UUID                 | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Value is                | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Value in                | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| Regex Match             | ✅ (Scheduled only) |        ❌       |          ✅         |           ✅           |
| %Negative               | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| %Zero                   | ✅ (Scheduled only) |        ✅       |          ❌         |           ✅           |
| Cardinality             |          ❌         |        ❌       |          ❌         |           ✅           |
| **Other Test Types**    |                    |                |                    |                       |
| Custom SQL              |          ✅         |        ❌       |          ❌         |           ❌           |
| Schema Drift            |          ❌         |        ❌       |          ❌         |           ❌           |
| Job Failure             |          ❌         |        ❌       |          ❌         |           ❌           |

### Mode and scheduling rules

* `mode` determines whether a monitor is scheduled or on-demand.
* `mode` determines whether a monitor is scheduled or on-demand. Use the exact API token values for this field: `scheduled` or `on_demand`.
* Scheduled monitors:
  * `frequency` is required.
* On-demand monitors:
  * `frequency` must be omitted.
  * Only a subset of `test_type` values are allowed (see “On-demand compatible tests”).

#### Frequency shapes and constraints

This controls how often a scheduled monitor runs. The available frequency options depend on the selected row creation mode.

**Frequency availability by row creation mode:**

| Row Creation Mode           | Hourly (1H, 3H, 6H, 12H) | Daily | Weekly | Monthly |
| --------------------------- | :----------------------: | :---: | :----: | :-----: |
| Timestamp (datetime column) |             ✅            |   ✅   |    ✅   |    ✅    |
| Timestamp (date column)     |             ❌            |   ✅   |    ✅   |    ✅    |
| SQL Expression              |             ✅            |   ✅   |    ✅   |    ✅    |
| All Records                 |             ✅            |   ✅   |    ✅   |    ✅    |

**Frequency object shapes:**

**Hourly Frequency**

```json
{
  "frequency": "1H" | "3H" | "6H" | "12H"
}
```

* Must NOT include timezone or time-of-day fields
* Not available when using date columns (only datetime)

**Daily Frequency**

```json
{
  "frequency": "1D",
  "time_of_day": <integer>,
  "timezone": "<string>"
}
```

* Requires `time_of_day` (hour of day, 0-23) and `timezone`

**Weekly Frequency**

```json
{
  "frequency": "7D",
  "time_of_day": <integer>,
  "day_of_week": <integer>,
  "timezone": "<string>"
}
```

* Requires `time_of_day`, `day_of_week` (0=Sunday, 6=Saturday), and `timezone`

**Monthly Frequency**

```json
{
  "frequency": "MS",
  "time_of_day": <integer>,
  "day_of_month": <integer>,
  "timezone": "<string>"
}
```

* Requires `time_of_day`, `day_of_month`, and `timezone`
* `day_of_month`: provide integer values 1-28 for monitor to be run on these dates of the month.
  * For monitor to run on every last day of the month, use `"day_of_month": 31`

**Additional validation rules:**

* `timezone` must be a valid IANA time zone (e.g., `UTC`, `America/New_York`)
* `day_of_week` is only valid for weekly frequency; providing it for other frequencies is rejected
* `day_of_month` is only valid for monthly frequency; providing it for other frequencies is rejected
* `time_of_day` hour range is validated by the server (0-23)

### Row creation modes and constraints

`row_creation` controls how rows are selected for computing metrics/tests. This setting is required for most test types and has different availability based on the monitor mode and test type.

#### Row creation mode availability

| Test Type               | Monitor Mode | Timestamp | SQL Expression | All Records | Notes                         |
| ----------------------- | ------------ | :-------: | :------------: | :---------: | ----------------------------- |
| **Dataset-Level Tests** |              |           |                |             |                               |
| Freshness               | On-demand    |     ✅     |        ✅       |      ❌      | Requires time-based filtering |
| Freshness               | Scheduled    |     ✅     |        ✅       |      ✅      | All modes supported           |
| Volume                  | On-demand    |     ✅     |        ✅       |      ✅      | All modes supported           |
| Volume                  | Scheduled    |     ✅     |        ✅       |      ✅      | All modes supported           |
| **Field Health Tests**  |              |           |                |             |                               |
| All field health        | On-demand    |     ✅     |        ✅       |      ✅      | All modes supported           |
| All field health        | Scheduled    |     ✅     |        ✅       |      ✅      | All modes supported           |
| **Other Test Types**    |              |           |                |             |                               |
| Custom SQL              | On-demand    |     ❌     |        ❌       |      ❌      | Row creation not applicable   |
| Custom SQL              | Scheduled    |     ❌     |        ❌       |      ❌      | Row creation not applicable   |
| Schema Drift            | Scheduled    |     ❌     |        ❌       |      ❌      | Row creation not applicable   |
| Job Failure             | Scheduled    |     ❌     |        ❌       |      ❌      | Row creation not applicable   |

#### Row creation mode specifications

**AllRecordsMode**

```json
{
  "filter_mode": "all_records"
}
```

* Use all rows in the dataset
* No additional fields required
* Smart training is not available for this mode.

**TimestampMode**

```json
{
  "filter_mode": "timestamp",
  "metric_column_id": <number>,
  "enable_smart_training": <boolean> // optional
}
```

* Requires `metric_column_id` referencing a timestamp/datetime column
* Column must exist on the target asset and be timestamp-like data type
* Optionally supports `enable_smart_training`

**SqlExpressionMode**

```json
{
  "filter_mode": "sql_expression",
  "sql_expression": "<string>",
  "enable_smart_training": <boolean> // optional
}
```

* Requires `sql_expression` (a boolean filter SQL expression)
* Expression is validated for syntax against the underlying source via connector
* Invalid SQL will be rejected with timeout/error if source cannot be reached
* Optionally supports `enable_smart_training`

#### Lookback period constraints

| Row Creation Mode | Lookback Period Required | Notes       |
| ----------------- | :----------------------: | ----------- |
| Timestamp         |             ✅            | Must be > 0 |
| SQL Expression    |             ✅            | Must be > 0 |
| All Records       |             ❌            | -           |

For on-demand monitors, lookback period behavior depends on the row creation mode:

**Note**: `row_creation` enum values are case-sensitive; use lowercase values as shown above.

### Grouping and group mapping

This allows monitors to be run on specific segments within a table (e.g., by values in a dimension column). See [Set Up Grouped-by Monitors](https://docs.decube.io/data-quality/how-to-set-up-monitors/set-up-grouped-by-monitors) for UI setup details.

* `is_group_by = true` enables grouping; otherwise grouping-related fields are ignored.
* `group_by` identifies the asset to group by (must be compatible with the target asset and monitor setting).
* `groups` is an optional allowlist of specific group values to monitor. If provided, it must not exceed the server’s limit (current max is 100 distinct values).

#### Custom SQL grouping

This allows

* `group_mapping` is optional and allows mapping the raw grouping values to business labels:
  * Fields: `mapping_column_id` (column containing raw values), `group_by_field_name` (target label field name).
* Use the `GET /monitors/distinct_groups?column_id=...` helper to discover distinct group values for a column.

### Alerts and notifications

* `notify` controls whether alerts are sent. If `notify = false`, any `custom_alerts` are ignored.
* `custom_alerts` supports channels:
  * `email`: list of addresses
  * `slack`: list of channel IDs or webhook URLs (org-config dependent)
  * `teams_webhook`: list of webhook URLs
* If `notify = true` and `custom_alerts` is provided, channel values must follow the organization’s connector configuration and be valid.

### Thresholds: validation rules and types by test type

Thresholds define the acceptable range or values for a test to pass. The shape and validation rules of the threshold depend on the `test_type` and `mode`.

The API now supports multiple threshold types:

* **AbsoluteRange**: Row count thresholds (e.g., "fail when > 100 rows")
* **PercentageRange**: Percentage thresholds (e.g., "fail when > 5%")
* **AnyRange**: Numeric range accepting any integer value
* **PositiveRange**: Numeric range accepting only non-negative values
* **AutoThreshold**: Machine learning-based thresholds (scheduled mode only)

{% hint style="info" %}
**Note on Regex Match test**: The regex pattern is now specified in the `value` field of the monitor configuration, not in the threshold. The threshold controls how many non-matching values trigger an incident.
{% endhint %}

#### Threshold types and validation rules

| Test Type                    | Monitor Mode | Threshold Type(s)                                   | Validation Rules                                                       | Notes                                             |
| ---------------------------- | ------------ | --------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------- |
| **No Threshold Required**    |              |                                                     |                                                                        |                                                   |
| Not Null                     | Both         | N/A                                                 | No threshold accepted                                                  | Automatically fails when null values found        |
| Is Unique                    | Both         | N/A                                                 | No threshold accepted                                                  | Automatically fails when duplicates found         |
| Is Email                     | Both         | N/A                                                 | No threshold accepted                                                  | Validates email format                            |
| Is UUID                      | Both         | N/A                                                 | No threshold accepted                                                  | Validates UUID format                             |
| Cardinality                  | Scheduled    | N/A                                                 | No threshold accepted                                                  | Monitors number of distinct values                |
| Freshness                    | Both         | N/A                                                 | Auto-learned                                                           | Uses historical patterns                          |
| Volume                       | Scheduled    | N/A                                                 | Auto-learned                                                           | Uses historical patterns                          |
| Schema Drift                 | Scheduled    | N/A                                                 | No threshold accepted                                                  | Detects schema changes                            |
| Job Failure                  | Scheduled    | N/A                                                 | No threshold accepted                                                  | Monitors job status                               |
| **AnyRange Thresholds**      |              |                                                     |                                                                        |                                                   |
| Average                      | Scheduled    | `AutoThreshold`, `AnyRange`                         | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value; auto for scheduled     |
| Average                      | On-demand    | `AnyRange`                                          | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value                         |
| Min                          | Scheduled    | `AutoThreshold`, `AnyRange`                         | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value; auto for scheduled     |
| Min                          | On-demand    | `AnyRange`                                          | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value                         |
| Max                          | Scheduled    | `AutoThreshold`, `AnyRange`                         | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value; auto for scheduled     |
| Max                          | On-demand    | `AnyRange`                                          | <p>-∞ ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>  | Accepts any numeric value                         |
| **PositiveRange Thresholds** |              |                                                     |                                                                        |                                                   |
| String Length                | Scheduled    | `AutoThreshold`, `PositiveRange`                    | <p>0 ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>   | Only non-negative integers; auto for scheduled    |
| String Length                | On-demand    | `PositiveRange`                                     | <p>0 ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>   | Only non-negative integers                        |
| Volume                       | On-demand    | `PositiveRange`                                     | <p>0 ≤ min ≤ max ≤ ∞<br>max > min<br>At least one bound required</p>   | Only non-negative integers                        |
| **Percentage & Absolute**    |              |                                                     |                                                                        |                                                   |
| Null %                       | Scheduled    | `AutoThreshold`, `PercentageRange`                  | <p>0 ≤ min ≤ max ≤ 100<br>max > min<br>At least one bound required</p> | Integer values only; auto for scheduled           |
| Null %                       | On-demand    | `PercentageRange`                                   | <p>0 ≤ min ≤ max ≤ 100<br>max > min<br>At least one bound required</p> | Integer values only                               |
| Unique %                     | Scheduled    | `AutoThreshold`, `PercentageRange`                  | <p>0 ≤ min ≤ max ≤ 100<br>max > min<br>At least one bound required</p> | Integer values only; auto for scheduled           |
| Unique %                     | On-demand    | `PercentageRange`                                   | <p>0 ≤ min ≤ max ≤ 100<br>max > min<br>At least one bound required</p> | Integer values only                               |
| Null                         | Scheduled    | `AutoThreshold`, `AbsoluteRange`, `PercentageRange` | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Null                         | On-demand    | `AbsoluteRange`, `PercentageRange`                  | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Unique                       | Scheduled    | `AutoThreshold`, `AbsoluteRange`, `PercentageRange` | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Unique                       | On-demand    | `AbsoluteRange`, `PercentageRange`                  | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Email                        | Scheduled    | `AutoThreshold`, `AbsoluteRange`, `PercentageRange` | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Email                        | On-demand    | `AbsoluteRange`, `PercentageRange`                  | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| UUID                         | Scheduled    | `AutoThreshold`, `AbsoluteRange`, `PercentageRange` | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| UUID                         | On-demand    | `AbsoluteRange`, `PercentageRange`                  | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Regex Match                  | Scheduled    | `AutoThreshold`, `AbsoluteRange`, `PercentageRange` | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| Regex Match                  | On-demand    | `AbsoluteRange`, `PercentageRange`                  | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | Supports both absolute and percentage             |
| **Custom SQL**               |              |                                                     |                                                                        |                                                   |
| Custom SQL                   | Scheduled    | `AbsoluteRange`, `PercentageRange`\*                | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | \*Percentage requires DQ Scorecard toggle enabled |
| Custom SQL                   | On-demand    | `AbsoluteRange`, `PercentageRange`\*                | <p>0 ≤ min ≤ max<br>max > min<br>At least one bound required</p>       | \*Percentage requires DQ Scorecard toggle enabled |

* **Note for CustomSQL monitor**: PercentageRange thresholds can only be set when `total_row_count_query` is provided in the payload. This is to allow calculation of percentage-based metrics by defining the total row count for the CustomSQL monitor.

#### Threshold object shapes

The API accepts discriminated threshold object shapes. Each shape includes a required `type` field whose value is a literal constant that determines which threshold type is being used:

**AbsoluteRange**

```json
{
  "type": "absolute",
  "min": <integer|null>,
  "max": <integer|null>
}
```

* Used for absolute row count thresholds
* `min` and `max` may be `null` to indicate an open bound
* At least one bound (min or max) must be non-null
* Both values must be non-negative integers (≥ 0)
* If both are provided: `max` > `min`
* Example: `{"type": "absolute", "min": null, "max": 100}` - fails when > 100 rows

**PercentageRange**

```json
{
  "type": "percentage",
  "min": <integer|null>,
  "max": <integer|null>
}
```

* Used for percentage-based thresholds
* `min` and `max` may be `null` to indicate an open bound
* At least one bound (min or max) must be non-null
* Values must be integers between 0 and 100 (inclusive)
* If both are provided: `max` > `min`
* Example: `{"type": "percentage", "min": null, "max": 5}` - fails when > 5%

**AnyRange**

```json
{
  "type": "any_range",
  "min": <integer|null>,
  "max": <integer|null>
}
```

* Used for numeric field tests that accept any integer value (positive or negative)
* `min` and `max` may be `null` to indicate an open bound
* At least one bound (min or max) must be non-null
* Accepts any integer value from -∞ to +∞
* If both are provided: `max` > `min`
* Commonly used for: Average, Min, Max tests
* Example: `{"type": "any_range", "min": -100, "max": 100}`

**PositiveRange**

```json
{
  "type": "positive_range",
  "min": <integer|null>,
  "max": <integer|null>
}
```

* Used for tests that only accept non-negative integer values
* `min` and `max` may be `null` to indicate an open bound
* At least one bound (min or max) must be non-null
* Both values must be non-negative integers (≥ 0)
* If both are provided: `max` > `min`
* Commonly used for: String Length, Volume (on-demand)
* Example: `{"type": "positive_range", "min": 0, "max": 255}`

**AutoThreshold**

```json
{
  "type": "auto"
}
```

* Available for scheduled monitors that support machine learning
* Server auto-learns thresholds from historical data
* No additional fields required
* Only available for scheduled mode monitors

### Test-type specific notes

* Schema Drift tests (`table_addition`, `table_deletion`, `column_addition`, `column_deletion`, `column_type_change`) and Job Failure tests have their own specialized behavior and do not use thresholds, grouping, or row creation like field-health tests
* Freshness and Volume monitors (dataset-level) use auto-learned thresholds in scheduled mode and do not accept manual thresholds
* Custom SQL monitors:
  * Require query validation before submission
  * Support both `AbsoluteRange` and `PercentageRange` thresholds
  * **PercentageRange requires "Include this monitor into Data Quality Scorecard" toggle to be enabled**
  * When DQ Scorecard toggle is disabled, only `AbsoluteRange` is available
* New threshold-based tests (Null, Unique, Email, UUID, Regex Match):
  * Support both `AbsoluteRange` (row count) and `PercentageRange` (percentage) modes
  * Support `AutoThreshold` in scheduled mode
  * For Regex Match: the regex pattern is specified in the monitor's `value` field, not in the threshold

### Names and descriptions

* `name`: required, max 100 characters.
* `description`: optional, max 1000 characters.
* Name uniqueness is enforced within an asset/test-type/mode combination; if violated, requests will be rejected.

### Time zones

* `timezone` must be a valid [IANA time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Invalid zones are rejected.

### Appendix: Quick Field reference

* Frequency unions:
  * Hourly: {"frequency": "1H|3H|6H|12H"}
  * Daily: {"frequency": "1D", "time\_of\_day": int, "timezone": string}
  * Weekly: {"frequency": "7D", "time\_of\_day": int, "day\_of\_week": int, "timezone": string}
  * Monthly: {"frequency": "MS", "time\_of\_day": int, "day\_of\_month": int, "timezone": string}
    * acceptable values for `day_of_month`: 1-28, 31
* Row creation unions (literal `filter_mode` values):
  * All: { "filter\_mode": "all\_records" }
  * Timestamp: { "filter\_mode": "timestamp", "metric\_column\_id": number, "enable\_smart\_training"?: boolean }
  * SQL expression: { "filter\_mode": "sql\_expression", "sql\_expression": string, "enable\_smart\_training"?: boolean }
* Thresholds:
  * AbsoluteRange: `{ "type": "absolute", "min": <integer|null>, "max": <integer|null> }` (non-negative values)
  * PercentageRange: `{ "type": "percentage", "min": <integer|null>, "max": <integer|null> }` (0-100)
  * AnyRange: `{ "type": "any_range", "min": <integer|null>, "max": <integer|null> }` (any integer)
  * PositiveRange: `{ "type": "positive_range", "min": <integer|null>, "max": <integer|null> }` (non-negative values)
  * AutoThreshold: `{ "type": "auto" }`
