curl --request POST \
--url https://api.select.dev/v2/monitors/actions/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-tenant-id: <x-tenant-id>' \
--data '
{
"name": "<string>",
"trigger_config": {
"skip_if_empty": true,
"type": "digest"
},
"message_config": {
"sections": [
{
"section_type": "title",
"enabled": true
}
],
"title": "<string>",
"templated_values": {}
},
"notification_frequency_config": {
"frequency_type": "on_trigger"
},
"destination_ids": [
"<string>"
],
"cron": "<string>",
"display_in_feed": true,
"team_id": "<string>",
"budget_id": "<string>",
"snowflake_account_id": "<string>",
"partition_config": {
"partition_columns": [
{
"title": "<string>"
}
]
}
}
'import requests
url = "https://api.select.dev/v2/monitors/actions/validate"
payload = {
"name": "<string>",
"trigger_config": {
"skip_if_empty": True,
"type": "digest"
},
"message_config": {
"sections": [
{
"section_type": "title",
"enabled": True
}
],
"title": "<string>",
"templated_values": {}
},
"notification_frequency_config": { "frequency_type": "on_trigger" },
"destination_ids": ["<string>"],
"cron": "<string>",
"display_in_feed": True,
"team_id": "<string>",
"budget_id": "<string>",
"snowflake_account_id": "<string>",
"partition_config": { "partition_columns": [{ "title": "<string>" }] }
}
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-tenant-id': '<x-tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
trigger_config: {skip_if_empty: true, type: 'digest'},
message_config: {
sections: [{section_type: 'title', enabled: true}],
title: '<string>',
templated_values: {}
},
notification_frequency_config: {frequency_type: 'on_trigger'},
destination_ids: ['<string>'],
cron: '<string>',
display_in_feed: true,
team_id: '<string>',
budget_id: '<string>',
snowflake_account_id: '<string>',
partition_config: {partition_columns: [{title: '<string>'}]}
})
};
fetch('https://api.select.dev/v2/monitors/actions/validate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.select.dev/v2/monitors/actions/validate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'trigger_config' => [
'skip_if_empty' => true,
'type' => 'digest'
],
'message_config' => [
'sections' => [
[
'section_type' => 'title',
'enabled' => true
]
],
'title' => '<string>',
'templated_values' => [
]
],
'notification_frequency_config' => [
'frequency_type' => 'on_trigger'
],
'destination_ids' => [
'<string>'
],
'cron' => '<string>',
'display_in_feed' => true,
'team_id' => '<string>',
'budget_id' => '<string>',
'snowflake_account_id' => '<string>',
'partition_config' => [
'partition_columns' => [
[
'title' => '<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-tenant-id: <x-tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.select.dev/v2/monitors/actions/validate"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.select.dev/v2/monitors/actions/validate")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.select.dev/v2/monitors/actions/validate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"valid": true
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}Validate an unsaved monitor
Checks a monitor exactly as create would, without saving it or running anything: the body takes the shape create takes. Every query the monitor runs is checked against its query class, so a dimension, measure or filter the class does not have is rejected, naming the field, rather than failing the monitor’s scheduled runs. A monitor that fails a check is rejected with the reason. Requires monitors:write.
curl --request POST \
--url https://api.select.dev/v2/monitors/actions/validate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-tenant-id: <x-tenant-id>' \
--data '
{
"name": "<string>",
"trigger_config": {
"skip_if_empty": true,
"type": "digest"
},
"message_config": {
"sections": [
{
"section_type": "title",
"enabled": true
}
],
"title": "<string>",
"templated_values": {}
},
"notification_frequency_config": {
"frequency_type": "on_trigger"
},
"destination_ids": [
"<string>"
],
"cron": "<string>",
"display_in_feed": true,
"team_id": "<string>",
"budget_id": "<string>",
"snowflake_account_id": "<string>",
"partition_config": {
"partition_columns": [
{
"title": "<string>"
}
]
}
}
'import requests
url = "https://api.select.dev/v2/monitors/actions/validate"
payload = {
"name": "<string>",
"trigger_config": {
"skip_if_empty": True,
"type": "digest"
},
"message_config": {
"sections": [
{
"section_type": "title",
"enabled": True
}
],
"title": "<string>",
"templated_values": {}
},
"notification_frequency_config": { "frequency_type": "on_trigger" },
"destination_ids": ["<string>"],
"cron": "<string>",
"display_in_feed": True,
"team_id": "<string>",
"budget_id": "<string>",
"snowflake_account_id": "<string>",
"partition_config": { "partition_columns": [{ "title": "<string>" }] }
}
headers = {
"x-tenant-id": "<x-tenant-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-tenant-id': '<x-tenant-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: '<string>',
trigger_config: {skip_if_empty: true, type: 'digest'},
message_config: {
sections: [{section_type: 'title', enabled: true}],
title: '<string>',
templated_values: {}
},
notification_frequency_config: {frequency_type: 'on_trigger'},
destination_ids: ['<string>'],
cron: '<string>',
display_in_feed: true,
team_id: '<string>',
budget_id: '<string>',
snowflake_account_id: '<string>',
partition_config: {partition_columns: [{title: '<string>'}]}
})
};
fetch('https://api.select.dev/v2/monitors/actions/validate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.select.dev/v2/monitors/actions/validate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'trigger_config' => [
'skip_if_empty' => true,
'type' => 'digest'
],
'message_config' => [
'sections' => [
[
'section_type' => 'title',
'enabled' => true
]
],
'title' => '<string>',
'templated_values' => [
]
],
'notification_frequency_config' => [
'frequency_type' => 'on_trigger'
],
'destination_ids' => [
'<string>'
],
'cron' => '<string>',
'display_in_feed' => true,
'team_id' => '<string>',
'budget_id' => '<string>',
'snowflake_account_id' => '<string>',
'partition_config' => [
'partition_columns' => [
[
'title' => '<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-tenant-id: <x-tenant-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.select.dev/v2/monitors/actions/validate"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-tenant-id", "<x-tenant-id>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.select.dev/v2/monitors/actions/validate")
.header("x-tenant-id", "<x-tenant-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.select.dev/v2/monitors/actions/validate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-tenant-id"] = '<x-tenant-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"trigger_config\": {\n \"skip_if_empty\": true,\n \"type\": \"digest\"\n },\n \"message_config\": {\n \"sections\": [\n {\n \"section_type\": \"title\",\n \"enabled\": true\n }\n ],\n \"title\": \"<string>\",\n \"templated_values\": {}\n },\n \"notification_frequency_config\": {\n \"frequency_type\": \"on_trigger\"\n },\n \"destination_ids\": [\n \"<string>\"\n ],\n \"cron\": \"<string>\",\n \"display_in_feed\": true,\n \"team_id\": \"<string>\",\n \"budget_id\": \"<string>\",\n \"snowflake_account_id\": \"<string>\",\n \"partition_config\": {\n \"partition_columns\": [\n {\n \"title\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"valid": true
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}{
"title": "<string>",
"status": 123,
"detail": "<string>",
"code": "<string>",
"retryable": true,
"type": "about:blank",
"details": [
{}
]
}Authorizations
Organization API key (sl_…).
Headers
The organization ID the request is scoped to.
Body
A monitor to create, or the full replacement for an existing one.
The body carries every setting a read returns, except the ones the server
maintains. Filters naming a usage group or usage group set by name are stored
by reference, so a read returns them as templates resolved through
message_config.templated_values; sending that form back is equivalent.
A paragraph with no body_template, and a chart or table with no title,
gets generated ones, which a read returns.
The monitor's name, as it appears in the feed.
1The data the monitor reads. custom runs the monitor's own SQL, and requires a custom_sql_results section naming a saved statement by custom_sql_id, and a snowflake_account_id to run it against.
account_spend, organization_spend, warehouse, account_usage_group, organization_usage_group, workload, custom, insights, storage, select_org_spend, databricks_workload, databricks_query, bigquery_workload, bigquery_query, bigquery_projects, bigquery_reservation, bigquery_storage, budget Whether the monitor runs. A disabled or snoozed monitor is not scheduled.
enabled, disabled, snoozed How often the monitor runs. cron reads cron for the schedule.
hourly, daily, weekly, monthly, cron What the monitor checks, and the condition that makes it fire.
- DigestTrigger
- ConditionTrigger
- AnomalyProphetTrigger
- AnomalyPercentileTrigger
- BudgetThresholdTrigger
Show child attributes
Show child attributes
What the monitor's notification says when it fires.
Show child attributes
Show child attributes
How often a firing monitor is allowed to notify.
- MonitorNotificationFrequencyOnTrigger
- MonitorNotificationFrequencyOnStatusChange
- MonitorNotificationFrequencyLimitInTimePeriod
Show child attributes
Show child attributes
The alert destinations the monitor notifies when it fires. An empty list notifies no one: the monitor still runs, and its runs still appear in the feed while display_in_feed is true.
The cron expression the monitor runs on, in UTC. Required when schedule is cron, which only a monitor whose data_source is custom may use; null otherwise.
Whether the monitor's runs appear in the monitors feed.
The team that owns this monitor. Null leaves it to the organization, or to snowflake_account_id when that is set. Requires permission to write monitors for that team.
The budget this monitor watches. Null on a monitor that watches something other than a budget.
The Snowflake account this monitor reads, as listed by /v2/snowflake-accounts. Null reads the organization as a whole.
Splits the monitor into an independent check per distinct value of these columns. Null checks the data as a whole.
Show child attributes
Show child attributes
Response
Successful Response
The outcome of validating a monitor that passed every check.
Always true. A monitor that fails a check is rejected with the reason instead.

