curl --request POST \
--url https://sreagent.app/api/v1/config/outbound_rules \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"outbound_config_id": "<string>",
"cooldown_minutes": 123,
"enabled": true,
"escalate_after_minutes": 123,
"match_labels": {},
"match_severity": "<string>",
"match_source": "<string>",
"step_order": 123
}
'import requests
url = "https://sreagent.app/api/v1/config/outbound_rules"
payload = {
"name": "<string>",
"outbound_config_id": "<string>",
"cooldown_minutes": 123,
"enabled": True,
"escalate_after_minutes": 123,
"match_labels": {},
"match_severity": "<string>",
"match_source": "<string>",
"step_order": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
outbound_config_id: '<string>',
cooldown_minutes: 123,
enabled: true,
escalate_after_minutes: 123,
match_labels: {},
match_severity: '<string>',
match_source: '<string>',
step_order: 123
})
};
fetch('https://sreagent.app/api/v1/config/outbound_rules', 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://sreagent.app/api/v1/config/outbound_rules",
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>',
'outbound_config_id' => '<string>',
'cooldown_minutes' => 123,
'enabled' => true,
'escalate_after_minutes' => 123,
'match_labels' => [
],
'match_severity' => '<string>',
'match_source' => '<string>',
'step_order' => 123
]),
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://sreagent.app/api/v1/config/outbound_rules"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}")
req, _ := http.NewRequest("POST", 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.post("https://sreagent.app/api/v1/config/outbound_rules")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sreagent.app/api/v1/config/outbound_rules")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}"
response = http.request(request)
puts response.read_body{
"error": "<string>",
"message": "<string>"
}Create an outbound rule
Escalate the alerts a rule matches to one target, once per firing per alert. A rule with no match_source, match_severity or match_labels matches every alert in the organization. The target must be one of this organization’s own. Setting escalate_after_minutes makes it a timed rule instead, which pages for the alerts it matches once their firing has lasted that long; read that field’s description before setting it.
curl --request POST \
--url https://sreagent.app/api/v1/config/outbound_rules \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"outbound_config_id": "<string>",
"cooldown_minutes": 123,
"enabled": true,
"escalate_after_minutes": 123,
"match_labels": {},
"match_severity": "<string>",
"match_source": "<string>",
"step_order": 123
}
'import requests
url = "https://sreagent.app/api/v1/config/outbound_rules"
payload = {
"name": "<string>",
"outbound_config_id": "<string>",
"cooldown_minutes": 123,
"enabled": True,
"escalate_after_minutes": 123,
"match_labels": {},
"match_severity": "<string>",
"match_source": "<string>",
"step_order": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
outbound_config_id: '<string>',
cooldown_minutes: 123,
enabled: true,
escalate_after_minutes: 123,
match_labels: {},
match_severity: '<string>',
match_source: '<string>',
step_order: 123
})
};
fetch('https://sreagent.app/api/v1/config/outbound_rules', 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://sreagent.app/api/v1/config/outbound_rules",
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>',
'outbound_config_id' => '<string>',
'cooldown_minutes' => 123,
'enabled' => true,
'escalate_after_minutes' => 123,
'match_labels' => [
],
'match_severity' => '<string>',
'match_source' => '<string>',
'step_order' => 123
]),
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://sreagent.app/api/v1/config/outbound_rules"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}")
req, _ := http.NewRequest("POST", 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.post("https://sreagent.app/api/v1/config/outbound_rules")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sreagent.app/api/v1/config/outbound_rules")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"outbound_config_id\": \"<string>\",\n \"cooldown_minutes\": 123,\n \"enabled\": true,\n \"escalate_after_minutes\": 123,\n \"match_labels\": {},\n \"match_severity\": \"<string>\",\n \"match_source\": \"<string>\",\n \"step_order\": 123\n}"
response = http.request(request)
puts response.read_body{
"error": "<string>",
"message": "<string>"
}Authorizations
An sre_ak_* API key holding the api:admin scope (or api:config_read, which every write refuses with read_only_key).
Body
What this rule is called here. It is a label for the people reading the table, not anything the target sees.
The target this rule escalates to, by its uuid as list_outbound_configs answers it. It must belong to this organization.
An immediate rule waits this long, at least 1, after a delivered page before it pages about a DIFFERENT alert; a page the target refused spends nothing, so every matching alert still gets its own attempt and its own row. A timed rule does not space its pages by this at all: one scheduled evaluation pages for every alert it matches whose firing has lasted long enough, and the number is read only as the seed of the retry wait below. Either kind of rule waits this long before re-attempting a page that could not be delivered, doubling the wait with each further failure up to one day; the immediate path makes that attempt on the next delivery of the alert that arrives after the wait, and the timed path on its next pass. Neither repeats a page that was delivered for the same firing. null leaves the default of 30 minutes.
Whether this rule may fire at all. A disabled rule keeps everything it matches on and is skipped.
Makes this a timed rule, at least 1, and it changes when the rule pages rather than what it pages for. A timed rule is run by a scheduled evaluation, which pages once per firing for the alerts it matches, and only once the firing has lasted this many minutes; an alert that cleared and fired again is firing since the moment it came back, however long it was open before that. match_source, match_severity and match_labels are read the same way as on an immediate rule. A page the target refuses is attempted again at growing intervals, starting at cooldown_minutes after the failure and doubling with each further failure up to one day, and one that was delivered is never repeated for that alert and rule in that firing. null leaves the rule immediate, and an immediate rule pages for the alerts it matches as they arrive: once per firing per alert, so a redelivery of an alert that is still active does not page again and an alert that cleared and fired again does.
Only alerts whose labels carry every one of these pairs, compared as strings, so every value here must be a string. An empty object and null both match every alert.
Only alerts of this severity, matched exactly, one of: critical, high, warning, medium, low, info. null matches every severity.
Only alerts from this source, matched exactly, one of: grafana, pagerduty, opsgenie, prometheus, alertmanager, datadog, newrelic, cloudwatch, cloudtrail, custom, slo_breach, slo_tracking, certificate_monitor, cost_monitor, synthetic_check, slack, overseer, security. null matches every source.
Where this rule sits in an escalation chain. Step 0 pages first; a rule with a higher step order is skipped for a firing somebody already acknowledged, and waits for a step 0 page that nobody acknowledged before it pages. Leave it at 0 for a rule that is not part of a chain.
Response
Created.

