# Create a dashboard alert

Creates a new alert for a specific dashboard chart.

[endpoint]
base_url = "https://telemetry.betterstack.com"
path = "/api/v2/dashboards/{dashboard_id}/charts/{chart_id}/alerts"
method = "POST"

[[path_param]]
name = "dashboard_id"
description = "The unique identifier of the dashboard."
required = true
type = "integer"

[[path_param]]
name = "chart_id"
description = "The unique identifier of the chart."
required = true
type = "integer"

[[body_param]]
name = "name"
description = "The name of the alert."
required = true
type = "string"

[[body_param]]
name = "alert_type"
description = "The type of alert. `threshold` for static values, `relative` for percentage changes, or `anomaly_rrcf` for ML-based anomaly detection."
required = true
type = "string"

[[body_param]]
name = "operator"
description = "The comparison operator. Required for `threshold` and `relative` alerts. For `threshold`: `equal`, `not_equal`, `higher_than`, `higher_than_or_equal`, `lower_than`, `lower_than_or_equal`. For `relative`: `increases_by`, `decreases_by`, `changes_by`. Not used for `anomaly_rrcf` alerts."
required = false
type = "string"

[[body_param]]
name = "value"
description = "The numeric value for the alert condition. For `threshold` alerts, this is the static threshold. For `relative` alerts, this is the percentage change. Required for `threshold` and `relative` types unless `string_value` is set. A value of `0` is valid."
required = false
type = "number"

[[body_param]]
name = "string_value"
description = "An alternative to `value` for `threshold` alerts when matching an exact string. If `string_value` is set, `value` is not required. Only valid with `equal` or `not_equal` operators."
required = false
type = "string"

[[body_param]]
name = "check_period"
description = "How often to evaluate the alert condition, in seconds. Required for `threshold` and `relative` alert types. Not used for `anomaly_rrcf` alerts."
required = true
type = "integer"

[[body_param]]
name = "query_period"
description = "The time window in seconds for the data being analyzed. If not provided, falls back to `aggregation_interval`, then `check_period`."
required = false
type = "integer"

[[body_param]]
name = "aggregation_interval"
description = "The size of data buckets in seconds for aggregating and evaluating the metric. If not provided, falls back to `query_period`, then `check_period`."
required = false
type = "integer"

[[body_param]]
name = "confirmation_period"
description = "The duration in seconds that a condition must be met before an alert is triggered. A value of `0` triggers the alert immediately. Default: `0`."
required = false
type = "integer"

[[body_param]]
name = "recovery_period"
description = "The duration in seconds that a condition must be resolved before an incident is recovered."
required = false
type = "integer"

[[body_param]]
name = "anomaly_sensitivity"
description = "The sensitivity of the anomaly detection model, from 0 to 100. Higher values result in more alerts. Only for `anomaly_rrcf` alerts."
required = false
type = "number"

[[body_param]]
name = "anomaly_trigger"
description = "Defines which anomalies trigger an alert: `any` (both higher and lower), `higher`, or `lower`. Only for `anomaly_rrcf` alerts."
required = false
type = "string"

[[body_param]]
name = "series_names"
description = "An array of strings to filter the alert to specific data series."
required = false
type = "array"

[[body_param]]
name = "source_variable"
description = "The variable name for the source selection. If not provided, derived automatically from the dashboard preset's source variable."
required = false
type = "string"

[[body_param]]
name = "source_mode"
description = "The mode for source selection. Valid values: `source_variable`, `platforms_single_source`, `platforms_all_sources`."
required = false
type = "string"

[[body_param]]
name = "source_platforms"
description = "An array of platform names to filter the sources this alert runs on."
required = false
type = "array"

[[body_param]]
name = "incident_cause"
description = "A custom description template for the incident created by this alert. Supports `{{value}}` placeholder."
required = false
type = "string"

[[body_param]]
name = "incident_per_series"
description = "Whether a separate incident will be created for each data series that triggers the alert."
required = false
type = "boolean"

[[body_param]]
name = "escalation_target"
description = "Defines where to send notifications. Defaults to `current_team`, for details see [Escalation targets](#escalation-targets)."
required = false
type = "object"

[[body_param]]
name = "call"
description = "Enable phone call notifications. Only used if `escalation_target` is not a policy."
required = false
type = "boolean"

[[body_param]]
name = "sms"
description = "Enable SMS notifications. Only used if `escalation_target` is not a policy."
required = false
type = "boolean"

[[body_param]]
name = "email"
description = "Enable email notifications. Only used if `escalation_target` is not a policy."
required = false
type = "boolean"

[[body_param]]
name = "push"
description = "Enable push notifications. Only used if `escalation_target` is not a policy."
required = false
type = "boolean"

[[body_param]]
name = "critical_alert"
description = "Enable critical push notifications that bypass Do Not Disturb. Only used if `escalation_target` is not a policy."
required = false
type = "boolean"

[[body_param]]
name = "metadata"
description = "A key-value object for custom metadata to be included in incidents. Both keys and values must be strings. For details, see [Metadata](#metadata)."
required = false
type = "object"

[[body_param]]
name = "paused"
description = "Set to `true` to create the alert in a paused state."
required = false
type = "boolean"

[[header]]
name = "Authorization"
description = "Bearer `$TOKEN`"
required = true
type = "string"
[/endpoint]

[responses]
[[response]]
status = 201
description = "The alert was created successfully."
body = '''
{
  "data": {
    "id": "790",
    "type": "alert",
    "attributes": {
      "name": "High Error Rate",
      "alert_type": "threshold",
      "operator": "higher_than",
      "value": 100.0,
      "paused": false
    }
  }
}
'''

[[response]]
status = 422
description = "Validation failed, e.g., due to an incompatible chart type."
body = '''
{
  "errors": "Sorry, some values are incorrect",
  "invalid_values": {
    "chart_type": "Alerts are not supported for chart type 'pie_chart'."
  }
}
'''
[/responses]

[note]
Alerts can only be created on charts with compatible types: `line_chart`, `bar_chart`, `number_chart`, `tail_chart`, or `table_chart`.
[/note]

## Example requests
[code-tabs]
```shell
[label Threshold alert]
curl --request POST \
  --url https://telemetry.betterstack.com/api/v2/dashboards/123/charts/456/alerts \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "High Error Rate",
    "alert_type": "threshold",
    "operator": "higher_than",
    "value": 100,
    "check_period": 300,
    "confirmation_period": 0,
    "escalation_target": { "policy_name": "Critical Policy" },
    "metadata": { "runbook": "http://runbook/high-errors" }
  }'
```
```shell
[label String value alert]
curl --request POST \
  --url https://telemetry.betterstack.com/api/v2/dashboards/123/charts/456/alerts \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Status is Error",
    "alert_type": "threshold",
    "operator": "equal",
    "string_value": "error",
    "check_period": 300,
    "confirmation_period": 0
  }'
```
[/code-tabs]

## Alert types and attributes

The attributes in the alert response vary based on the `alert_type`.

[code-tabs]
```json
[label Threshold/Relative Response]
{
  "operator": "higher_than",
  "value": 100,
  "string_value": null,
  "check_period": 300
}
```
```json
[label Anomaly Response]
{
  "anomaly_sensitivity": 75.0,
  "anomaly_trigger": "any"
}
```
[/code-tabs]

[info]
For `threshold` and `relative` alerts, the fields `anomaly_sensitivity` and `anomaly_trigger` are omitted. For `anomaly_rrcf` alerts, the fields `operator`, `value`, `string_value`, and `check_period` are omitted.
[/info]

## Escalation targets

The `escalation_target` object determines where notifications are sent:

- For current team, use `"current_team"` as a string.

- Reference a different team using `{ "team_id": 123 }` or `{ "team_name": "Ops Team" }`.

- Reference [an escalation policy](https://betterstack.com/docs/uptime/escalation-policies/) using `{ "policy_id": 456 }` or `{ "policy_name": "Critical Policy" }`. When escalating to a policy, notification channels (`call`, `sms`, etc.) are managed by the policy itself and are ignored in the API request.

## Metadata

The `metadata` object allows you to attach custom key-value pairs to an alert. This information is included in incident notifications for extra context. Both keys and values must be strings.

```json
[label Metadata example]
{
  "metadata": {
    "environment": "production",
    "runbook": "https://wiki.example.com/runbooks/high-error-rate"
  }
}
```