Saves the CALLER's alerting configuration layer (one row per
organization in alert_config_layers). The body is an
AlertingConfigLayer: three channel toggles plus three recipient
lists. Each recipient carries its own severities[]; email
recipients additionally carry language and format.
After save, the effective per-tenant Mimir YAML is recomputed
server-side (merge of all layers walking up to the Owner) and
pushed to every tenant in the caller's hierarchy with bounded
concurrency. Up to 10 tenants are pushed inside the request and
per-tenant failures are returned in warnings[]; larger fan-outs
run in the background (propagation: async) with retries, and their
progress is reported by GET /alerts/config in propagation.
The caller's layer is saved regardless of push outcome (Mimir can
be reconciled by saving again).
Additive-only contract: descendants can ADD recipients but cannot
disable channels enabled by ancestors. The server normalises any
explicit false in enabled.{email,webhook,telegram} from
non-Owner layers to null on storage.
Save+propagate is serialised per-organization (in-process mutex) to prevent two concurrent saves from racing at the Mimir push step. Body is capped at 1 MiB; oversized payloads are rejected with 413.
Requires manage:alerts permission.
Body
Required
-
Per-layer enable/disable for each notification channel. Each value is tri-state:
true— explicitly enabled at this layerfalse— explicitly disabled (Owner only; non-Owner false is normalised to null on save)null— no opinion at this layer; effective state inherits from the merge of any ancestor layer that took a position. If no layer in the chain enables a channel, the channel stays off.
-
Not more than
50elements. -
Not more than
20elements. -
Not more than
20elements.
Responses
-
Layer saved (and propagation attempted)
-
Validation failed.
data.typeis alwaysvalidation_error.data.errors[]lists per-field failures withkeyset to the JSON path (with dotted array indices, e.g.email_recipients.2.address),messageto a stable machine code (required,invalid_format,invalid_value,invalid_scheme,host_not_allowed,must_be_future, ...) andvalueto the offending input when not sensitive. -
Unauthorized - invalid or missing token
-
Forbidden - insufficient permissions
-
Request body exceeds the configured maximum (1 MiB).
-
Internal server error
curl \
--request POST 'https://my.nethesis.it/backend/api/alerts/config' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"enabled": {
"email": true,
"webhook": true,
"telegram": false
},
"email_recipients": [
{
"address": "noc@msp.example",
"severities": [],
"language": "it",
"format": "html"
}
],
"webhook_recipients": [
{
"name": "central-siem",
"url": "https://siem.example/api/alerts",
"severities": []
}
],
"telegram_recipients": []
}'
{
"enabled": {
"email": true,
"webhook": true,
"telegram": false
},
"email_recipients": [
{
"address": "noc@msp.example",
"severities": [],
"language": "it",
"format": "html"
}
],
"webhook_recipients": [
{
"name": "central-siem",
"url": "https://siem.example/api/alerts",
"severities": []
}
],
"telegram_recipients": []
}
{
"enabled": {
"email": null,
"webhook": null,
"telegram": null
},
"email_recipients": [
{
"address": "noc@reseller.example",
"severities": [
"critical",
"warning"
],
"language": "en",
"format": "html"
}
],
"webhook_recipients": [],
"telegram_recipients": []
}
{
"enabled": {
"email": null,
"webhook": null,
"telegram": null
},
"email_recipients": [
{
"address": "oncall@customer.example",
"severities": [
"critical"
],
"language": "en",
"format": "plain"
},
{
"address": "manager@customer.example",
"severities": [],
"language": "it",
"format": "html"
}
],
"webhook_recipients": [],
"telegram_recipients": []
}
{
"enabled": {
"email": true,
"webhook": null,
"telegram": null
},
"email_recipients": [
{
"address": "noc@distributor.example",
"severities": [
"critical"
],
"language": "en",
"format": "html",
"scope": {
"managed_organization_ids": [
"reseller_logto_id"
]
}
},
{
"address": "tech@distributor.example",
"severities": [],
"language": "it",
"format": "html",
"scope": {
"assigned_organization_ids": [
"distributor_logto_id"
],
"system_ids": [
"1e3f8790-0c66-4727-9139-59a4dc50f41b"
]
}
}
],
"webhook_recipients": [],
"telegram_recipients": []
}
{
"enabled": {
"email": null,
"webhook": null,
"telegram": null
},
"email_recipients": [],
"webhook_recipients": [
{
"name": "ops-slack",
"url": "https://hooks.slack.com/services/T000/B000/XXX",
"severities": [
"critical"
]
}
],
"telegram_recipients": []
}
{
"enabled": {
"email": null,
"webhook": null,
"telegram": true
},
"email_recipients": [],
"webhook_recipients": [],
"telegram_recipients": [
{
"bot_token": "123456:ABC-DEF1234ghIkl",
"chat_id": -1001234567890,
"severities": []
}
]
}
{
"enabled": {
"email": null,
"webhook": null,
"telegram": null
},
"email_recipients": [],
"webhook_recipients": [],
"telegram_recipients": []
}
{
"code": 200,
"message": "alerting configuration updated successfully",
"data": {
"affected_tenants": 42,
"propagation": "sync",
"propagated_to": 42,
"warnings": [
"string"
]
}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "email_recipients.2.address",
"message": "invalid_format",
"value": "wwwwwww"
}
]
}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "webhook_recipients.0.url",
"message": "invalid_scheme",
"value": "asdf"
}
]
}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "webhook_recipients.0.name",
"message": "required"
}
]
}
}
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "email_recipients.0.severities.0",
"message": "invalid_value",
"value": "fatal"
}
]
}
}
{
"code": 401,
"message": "invalid token",
"data": {}
}
{
"code": 403,
"message": "insufficient permissions",
"data": {}
}
{
"code": 413,
"message": "request body exceeds the configured maximum"
}
{
"code": 500,
"message": "internal server error",
"data": {}
}