curl --request PUT \
--url https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"rule": {
"version": 1,
"window": "<string>",
"conditions": [
{
"threshold": 123
}
],
"groupBy": [
"<string>"
],
"filters": [
{}
],
"maxInstances": 250,
"settings": {},
"for": "<string>",
"overrides": [
{
"match": {},
"conditions": [
{
"threshold": 123
}
],
"for": "<string>",
"settings": {}
}
]
},
"contactPointID": "<string>",
"description": "<string>",
"labels": {}
}
'import requests
url = "https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}"
payload = {
"name": "<string>",
"rule": {
"version": 1,
"window": "<string>",
"conditions": [{ "threshold": 123 }],
"groupBy": ["<string>"],
"filters": [{}],
"maxInstances": 250,
"settings": {},
"for": "<string>",
"overrides": [
{
"match": {},
"conditions": [{ "threshold": 123 }],
"for": "<string>",
"settings": {}
}
]
},
"contactPointID": "<string>",
"description": "<string>",
"labels": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
rule: {
version: 1,
window: '<string>',
conditions: [{threshold: 123}],
groupBy: ['<string>'],
filters: [{}],
maxInstances: 250,
settings: {},
for: '<string>',
overrides: [{match: {}, conditions: [{threshold: 123}], for: '<string>', settings: {}}]
},
contactPointID: '<string>',
description: '<string>',
labels: {}
})
};
fetch('https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}', 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.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'rule' => [
'version' => 1,
'window' => '<string>',
'conditions' => [
[
'threshold' => 123
]
],
'groupBy' => [
'<string>'
],
'filters' => [
[
]
],
'maxInstances' => 250,
'settings' => [
],
'for' => '<string>',
'overrides' => [
[
'match' => [
],
'conditions' => [
[
'threshold' => 123
]
],
'for' => '<string>',
'settings' => [
]
]
]
],
'contactPointID' => '<string>',
'description' => '<string>',
'labels' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}")
req, _ := http.NewRequest("PUT", url, payload)
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.put("https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"valueFormat": {
"unit": "percent",
"decimals": 1,
"suffix": "<string>"
},
"vocabulary": {
"value": {
"key": "<string>",
"name": "<string>",
"help": "<string>"
},
"measures": [
{
"key": "<string>",
"name": "<string>",
"help": "<string>",
"detailKey": "<string>",
"reference": true
}
],
"minimum": {
"key": "<string>",
"name": "<string>",
"help": "<string>",
"detailKey": "<string>",
"reference": true
},
"gateMeasure": "<string>",
"settings": [
{
"key": "<string>",
"name": "<string>",
"help": "<string>"
}
]
},
"name": "<string>",
"ruleType": "login_success_rate",
"rule": {
"version": 1,
"type": "login_success_rate",
"window": "<string>",
"conditions": [
{
"severity": "info",
"operator": "above",
"threshold": 123
}
],
"groupBy": [
"<string>"
],
"filters": [
{}
],
"maxInstances": 250,
"settings": {},
"recovery": {
"operator": "above",
"threshold": 123
},
"for": "<string>",
"noData": "ok",
"evaluationHours": {
"mode": "always",
"timezone": "<string>",
"ranges": [
{
"weekdays": [
"mon"
],
"start": "09:00",
"end": "18:00"
}
]
},
"overrides": [
{
"match": {},
"conditions": [
{
"severity": "info",
"operator": "above",
"threshold": 123
}
],
"recovery": {
"operator": "above",
"threshold": 123
},
"for": "<string>",
"noData": "ok",
"settings": {},
"evaluationHours": {
"mode": "always",
"timezone": "<string>",
"ranges": [
{
"weekdays": [
"mon"
],
"start": "09:00",
"end": "18:00"
}
]
}
}
]
},
"contactPointID": "<string>",
"contactPointName": "<string>",
"status": "active",
"instanceTotals": {
"normal": 123,
"pending": 123,
"firing": 123,
"noData": 123,
"error": 123,
"total": 123
},
"createdMs": 123,
"updatedMs": 123,
"description": "<string>",
"labels": {},
"lastEvaluatedMs": 123,
"lastErrorReason": "rule_type_not_implemented",
"lastErrorMessage": "<string>",
"last7d": [
{
"date": "2026-10-07",
"hasEvaluations": true,
"firing": 123,
"pending": 123,
"noData": 123,
"normal": 123,
"outsideEvaluationHours": 123
}
]
}{
"error": {
"message": "Validation failed",
"details": [
{
"field": "projectID",
"message": "required"
}
]
}
}Update alert rule
Updates an Observe alert rule.
Required API key permission: observe:alerts:write.
curl --request PUT \
--url https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"rule": {
"version": 1,
"window": "<string>",
"conditions": [
{
"threshold": 123
}
],
"groupBy": [
"<string>"
],
"filters": [
{}
],
"maxInstances": 250,
"settings": {},
"for": "<string>",
"overrides": [
{
"match": {},
"conditions": [
{
"threshold": 123
}
],
"for": "<string>",
"settings": {}
}
]
},
"contactPointID": "<string>",
"description": "<string>",
"labels": {}
}
'import requests
url = "https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}"
payload = {
"name": "<string>",
"rule": {
"version": 1,
"window": "<string>",
"conditions": [{ "threshold": 123 }],
"groupBy": ["<string>"],
"filters": [{}],
"maxInstances": 250,
"settings": {},
"for": "<string>",
"overrides": [
{
"match": {},
"conditions": [{ "threshold": 123 }],
"for": "<string>",
"settings": {}
}
]
},
"contactPointID": "<string>",
"description": "<string>",
"labels": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
rule: {
version: 1,
window: '<string>',
conditions: [{threshold: 123}],
groupBy: ['<string>'],
filters: [{}],
maxInstances: 250,
settings: {},
for: '<string>',
overrides: [{match: {}, conditions: [{threshold: 123}], for: '<string>', settings: {}}]
},
contactPointID: '<string>',
description: '<string>',
labels: {}
})
};
fetch('https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}', 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.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'rule' => [
'version' => 1,
'window' => '<string>',
'conditions' => [
[
'threshold' => 123
]
],
'groupBy' => [
'<string>'
],
'filters' => [
[
]
],
'maxInstances' => 250,
'settings' => [
],
'for' => '<string>',
'overrides' => [
[
'match' => [
],
'conditions' => [
[
'threshold' => 123
]
],
'for' => '<string>',
'settings' => [
]
]
]
],
'contactPointID' => '<string>',
'description' => '<string>',
'labels' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}")
req, _ := http.NewRequest("PUT", url, payload)
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.put("https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloud.corbado.io/v1/observe/alertRules/{alertRuleID}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"rule\": {\n \"version\": 1,\n \"window\": \"<string>\",\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"groupBy\": [\n \"<string>\"\n ],\n \"filters\": [\n {}\n ],\n \"maxInstances\": 250,\n \"settings\": {},\n \"for\": \"<string>\",\n \"overrides\": [\n {\n \"match\": {},\n \"conditions\": [\n {\n \"threshold\": 123\n }\n ],\n \"for\": \"<string>\",\n \"settings\": {}\n }\n ]\n },\n \"contactPointID\": \"<string>\",\n \"description\": \"<string>\",\n \"labels\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"valueFormat": {
"unit": "percent",
"decimals": 1,
"suffix": "<string>"
},
"vocabulary": {
"value": {
"key": "<string>",
"name": "<string>",
"help": "<string>"
},
"measures": [
{
"key": "<string>",
"name": "<string>",
"help": "<string>",
"detailKey": "<string>",
"reference": true
}
],
"minimum": {
"key": "<string>",
"name": "<string>",
"help": "<string>",
"detailKey": "<string>",
"reference": true
},
"gateMeasure": "<string>",
"settings": [
{
"key": "<string>",
"name": "<string>",
"help": "<string>"
}
]
},
"name": "<string>",
"ruleType": "login_success_rate",
"rule": {
"version": 1,
"type": "login_success_rate",
"window": "<string>",
"conditions": [
{
"severity": "info",
"operator": "above",
"threshold": 123
}
],
"groupBy": [
"<string>"
],
"filters": [
{}
],
"maxInstances": 250,
"settings": {},
"recovery": {
"operator": "above",
"threshold": 123
},
"for": "<string>",
"noData": "ok",
"evaluationHours": {
"mode": "always",
"timezone": "<string>",
"ranges": [
{
"weekdays": [
"mon"
],
"start": "09:00",
"end": "18:00"
}
]
},
"overrides": [
{
"match": {},
"conditions": [
{
"severity": "info",
"operator": "above",
"threshold": 123
}
],
"recovery": {
"operator": "above",
"threshold": 123
},
"for": "<string>",
"noData": "ok",
"settings": {},
"evaluationHours": {
"mode": "always",
"timezone": "<string>",
"ranges": [
{
"weekdays": [
"mon"
],
"start": "09:00",
"end": "18:00"
}
]
}
}
]
},
"contactPointID": "<string>",
"contactPointName": "<string>",
"status": "active",
"instanceTotals": {
"normal": 123,
"pending": 123,
"firing": 123,
"noData": 123,
"error": 123,
"total": 123
},
"createdMs": 123,
"updatedMs": 123,
"description": "<string>",
"labels": {},
"lastEvaluatedMs": 123,
"lastErrorReason": "rule_type_not_implemented",
"lastErrorMessage": "<string>",
"last7d": [
{
"date": "2026-10-07",
"hasEvaluations": true,
"firing": 123,
"pending": 123,
"noData": 123,
"normal": 123,
"outsideEvaluationHours": 123
}
]
}{
"error": {
"message": "Validation failed",
"details": [
{
"field": "projectID",
"message": "required"
}
]
}
}Authorizations
Use an Observe API key from the management console. The key selects the project and must grant the permission listed on the operation. Keep this key on your server.
Path Parameters
Alert rule ID (format aru-<number>).
Body
Human-readable rule name.
Type of rule; names what the rule measures and selects the rule implementation and its settings shape.
login_success_rate, relative_flow_count, relative_subflow_count, absolute_flow_count The configuration of an alert rule: the generic envelope every rule type shares, plus one settings object belonging to the rule type named by type. Everything outside settings is implemented once, generically - the window is resolved and handed to the rule type as two absolute timestamps, and the conditions are applied to whatever number the rule type returned, so a rule type never sees the thresholds. Shape and vocabulary are validated here. The semantics that span fields - that the bands get stricter as the level does, that recovery sits on the lenient side of them, that the window is a whole number of days, and that groupBy names dimensions this project actually has - are validated when the rule is saved and again when it is evaluated, because only the second catches a project that changed after the rule was written.
Show child attributes
Show child attributes
Alert contact point ID (format acp-<number>) this rule notifies.
Optional longer description of the rule.
Optional static labels stored with the rule and returned on reads. They are not yet applied to the rule's alerts or notifications.
Show child attributes
Show child attributes
Rule status. Use to pause/resume a rule. Cannot be set to deleted here.
active, paused Response
Alert rule updated.
Alert rule ID (format aru-<number>).
How the values and thresholds of a rule type are written for people. Values and thresholds stay raw numbers in every response; apply this to display them.
Show child attributes
Show child attributes
What this rule calls its numbers and settings, resolved from its type and the variant its settings pick: "Logins counted" for a relative flow count rule counting logins.
Show child attributes
Show child attributes
login_success_rate, relative_flow_count, relative_subflow_count, absolute_flow_count The configuration of an alert rule: the generic envelope every rule type shares, plus one settings object belonging to the rule type named by type. Everything outside settings is implemented once, generically - the window is resolved and handed to the rule type as two absolute timestamps, and the conditions are applied to whatever number the rule type returned, so a rule type never sees the thresholds. Shape and vocabulary are validated here. The semantics that span fields - that the bands get stricter as the level does, that recovery sits on the lenient side of them, that the window is a whole number of days, and that groupBy names dimensions this project actually has - are validated when the rule is saved and again when it is evaluated, because only the second catches a project that changed after the rule was written.
Show child attributes
Show child attributes
Alert contact point ID (format acp-<number>) this rule notifies.
Name of the contact point this rule notifies, resolved from contactPointID so a rule can be displayed without a second request. Display-only - requests still reference the contact point by contactPointID.
active, paused How many of a rule's alert instances sit in each status, counted over all of them rather than over a page of them. This is what lets a rule row say "2 of 12 firing" without the client reading a single instance - and what keeps that number from quietly becoming "2 of however many were fetched" once a rule groups into more instances than one page holds. Every field is present, zero included, so a client can render the set without checking which keys exist. Counts include every instance the rule currently has.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
When the evaluation runner last attempted this rule, successfully or not. Absent means it has never been attempted, which every rule is for up to one evaluation interval after it is created or edited - a state worth showing rather than rendering as healthy.
Why the last evaluation attempt failed, absent when it succeeded. This is rule health, which is a different question from whether anything the rule watches is breaching: a rule here is not evaluating at all, so it is neither firing nor all-clear. An unclassified failure reports evaluation_failed rather than a value outside this list.
rule_type_not_implemented, config_invalid, series_not_available, dimension_not_available, too_many_instances, evaluation_failed The detail behind lastErrorReason, truncated for display. Absent when the last attempt succeeded.
How the rule's evaluations ended on each of the last 7 days, oldest first, the last entry being today so far. Days are calendar days in the project's timezone, the same days the rule statistics use, and lag up to about 30 minutes behind the evaluations. Returned by the alert rule list only. Absent when evaluation statistics are not available for the project.
7 elementsShow child attributes
Show child attributes
Was this page helpful?