curl --request POST \
--url https://api.coval.dev/v1/alerts \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "Low Resolution Rate Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"scope": "MONITORING",
"conditions": [
{
"metric_id": "01HZMETRIC0000000000000000",
"aggregation": "SINGLE",
"operator": "LT",
"threshold_float": 0.7
}
],
"channels": [
{
"channel_type": "SLACK",
"config": {
"channel_id": "C12345",
"channel_name": "#alerts"
}
}
]
}
'import requests
url = "https://api.coval.dev/v1/alerts"
payload = {
"name": "Low Resolution Rate Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"scope": "MONITORING",
"conditions": [
{
"metric_id": "01HZMETRIC0000000000000000",
"aggregation": "SINGLE",
"operator": "LT",
"threshold_float": 0.7
}
],
"channels": [
{
"channel_type": "SLACK",
"config": {
"channel_id": "C12345",
"channel_name": "#alerts"
}
}
]
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Low Resolution Rate Alert',
evaluation_type: 'ON_RUN_COMPLETE',
scope: 'MONITORING',
conditions: [
{
metric_id: '01HZMETRIC0000000000000000',
aggregation: 'SINGLE',
operator: 'LT',
threshold_float: 0.7
}
],
channels: [
{channel_type: 'SLACK', config: {channel_id: 'C12345', channel_name: '#alerts'}}
]
})
};
fetch('https://api.coval.dev/v1/alerts', 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.coval.dev/v1/alerts",
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' => 'Low Resolution Rate Alert',
'evaluation_type' => 'ON_RUN_COMPLETE',
'scope' => 'MONITORING',
'conditions' => [
[
'metric_id' => '01HZMETRIC0000000000000000',
'aggregation' => 'SINGLE',
'operator' => 'LT',
'threshold_float' => 0.7
]
],
'channels' => [
[
'channel_type' => 'SLACK',
'config' => [
'channel_id' => 'C12345',
'channel_name' => '#alerts'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.coval.dev/v1/alerts"
payload := strings.NewReader("{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.coval.dev/v1/alerts")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.coval.dev/v1/alerts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"ulid": "01HZ0EXAMPLE00000000000000",
"name": "Latency SLA Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"cooldown_seconds": 43200,
"trigger_count": 123,
"conditions": [
{
"ulid": "<string>",
"metric_id": "<string>",
"threshold_float": 123,
"threshold_string": "<string>",
"window_size_days": 183,
"window_size_runs": 5000,
"match_value": "<string>"
}
],
"channels": [
{
"ulid": "<string>",
"config": {}
}
],
"create_time": "2023-11-07T05:31:56Z",
"update_time": "2023-11-07T05:31:56Z",
"description": "",
"custom_message_template": "<string>",
"agent_ids": [
"<string>"
],
"required_tags": [
"<string>"
],
"scheduled_run_ids": [
"<string>"
],
"last_triggered_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "INVALID_ARGUMENT",
"message": "Invalid request body",
"details": [
{
"field": "conditions",
"description": "Value error, List should have at least 1 item after validation"
}
]
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "Authentication failed",
"details": [
{
"field": "X-API-Key",
"description": "Invalid or missing API key"
}
]
}
}{
"error": {
"code": "PERMISSION_DENIED",
"message": "Insufficient permissions",
"details": [
{
"field": "permissions",
"description": "Required scope: alerts:read"
}
]
}
}{
"error": {
"code": "ALREADY_EXISTS",
"message": "Alert name conflict",
"details": [
{
"field": "name",
"description": "An active alert named 'Latency SLA' already exists"
}
]
}
}{
"error": {
"code": "INTERNAL",
"message": "Internal server error",
"details": [
{
"description": "An unexpected error occurred"
}
]
}
}Create an alert
Creates a new alert with conditions and notification channels.
At least one condition is required. Channels are optional — an alert without channels will still evaluate and log events but won’t dispatch notifications.
curl --request POST \
--url https://api.coval.dev/v1/alerts \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "Low Resolution Rate Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"scope": "MONITORING",
"conditions": [
{
"metric_id": "01HZMETRIC0000000000000000",
"aggregation": "SINGLE",
"operator": "LT",
"threshold_float": 0.7
}
],
"channels": [
{
"channel_type": "SLACK",
"config": {
"channel_id": "C12345",
"channel_name": "#alerts"
}
}
]
}
'import requests
url = "https://api.coval.dev/v1/alerts"
payload = {
"name": "Low Resolution Rate Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"scope": "MONITORING",
"conditions": [
{
"metric_id": "01HZMETRIC0000000000000000",
"aggregation": "SINGLE",
"operator": "LT",
"threshold_float": 0.7
}
],
"channels": [
{
"channel_type": "SLACK",
"config": {
"channel_id": "C12345",
"channel_name": "#alerts"
}
}
]
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Low Resolution Rate Alert',
evaluation_type: 'ON_RUN_COMPLETE',
scope: 'MONITORING',
conditions: [
{
metric_id: '01HZMETRIC0000000000000000',
aggregation: 'SINGLE',
operator: 'LT',
threshold_float: 0.7
}
],
channels: [
{channel_type: 'SLACK', config: {channel_id: 'C12345', channel_name: '#alerts'}}
]
})
};
fetch('https://api.coval.dev/v1/alerts', 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.coval.dev/v1/alerts",
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' => 'Low Resolution Rate Alert',
'evaluation_type' => 'ON_RUN_COMPLETE',
'scope' => 'MONITORING',
'conditions' => [
[
'metric_id' => '01HZMETRIC0000000000000000',
'aggregation' => 'SINGLE',
'operator' => 'LT',
'threshold_float' => 0.7
]
],
'channels' => [
[
'channel_type' => 'SLACK',
'config' => [
'channel_id' => 'C12345',
'channel_name' => '#alerts'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.coval.dev/v1/alerts"
payload := strings.NewReader("{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.coval.dev/v1/alerts")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.coval.dev/v1/alerts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Low Resolution Rate Alert\",\n \"evaluation_type\": \"ON_RUN_COMPLETE\",\n \"scope\": \"MONITORING\",\n \"conditions\": [\n {\n \"metric_id\": \"01HZMETRIC0000000000000000\",\n \"aggregation\": \"SINGLE\",\n \"operator\": \"LT\",\n \"threshold_float\": 0.7\n }\n ],\n \"channels\": [\n {\n \"channel_type\": \"SLACK\",\n \"config\": {\n \"channel_id\": \"C12345\",\n \"channel_name\": \"#alerts\"\n }\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"ulid": "01HZ0EXAMPLE00000000000000",
"name": "Latency SLA Alert",
"evaluation_type": "ON_RUN_COMPLETE",
"cooldown_seconds": 43200,
"trigger_count": 123,
"conditions": [
{
"ulid": "<string>",
"metric_id": "<string>",
"threshold_float": 123,
"threshold_string": "<string>",
"window_size_days": 183,
"window_size_runs": 5000,
"match_value": "<string>"
}
],
"channels": [
{
"ulid": "<string>",
"config": {}
}
],
"create_time": "2023-11-07T05:31:56Z",
"update_time": "2023-11-07T05:31:56Z",
"description": "",
"custom_message_template": "<string>",
"agent_ids": [
"<string>"
],
"required_tags": [
"<string>"
],
"scheduled_run_ids": [
"<string>"
],
"last_triggered_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "INVALID_ARGUMENT",
"message": "Invalid request body",
"details": [
{
"field": "conditions",
"description": "Value error, List should have at least 1 item after validation"
}
]
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "Authentication failed",
"details": [
{
"field": "X-API-Key",
"description": "Invalid or missing API key"
}
]
}
}{
"error": {
"code": "PERMISSION_DENIED",
"message": "Insufficient permissions",
"details": [
{
"field": "permissions",
"description": "Required scope: alerts:read"
}
]
}
}{
"error": {
"code": "ALREADY_EXISTS",
"message": "Alert name conflict",
"details": [
{
"field": "name",
"description": "An active alert named 'Latency SLA' already exists"
}
]
}
}{
"error": {
"code": "INTERNAL",
"message": "Internal server error",
"details": [
{
"description": "An unexpected error occurred"
}
]
}
}Authorizations
API key for authentication
Body
Human-readable alert name
200When the alert evaluates
ON_RUN_COMPLETE 1Show child attributes
Show child attributes
2000Which runs the alert applies to
ALL, MONITORING, SIMULATION How multiple conditions are combined (AND vs OR)
ALL, ANY 0 <= x <= 864005000Show child attributes
Show child attributes
Response
Alert created
Alert ULID
^[0-9A-Z]{26}$"01HZ0EXAMPLE00000000000000"
Human-readable alert name
200"Latency SLA Alert"
Alert status
ACTIVE, DELETED When the alert evaluates
ON_RUN_COMPLETE Which runs the alert applies to
ALL, MONITORING, SIMULATION How multiple conditions are combined (AND vs OR)
ALL, ANY Minimum seconds between triggers
0 <= x <= 86400Number of times this alert has triggered
Evaluation conditions
Show child attributes
Show child attributes
Notification channels
Show child attributes
Show child attributes
Creation timestamp
Last update timestamp
Optional description
Custom notification message template
5000Restrict to specific agent IDs
Restrict to runs with these tags
Restrict to runs originating from these scheduled runs
Last trigger timestamp
Was this page helpful?