Create rules in bulk Experimental

POST /api/alerting/v2/rules/_bulk_create

Spaces method and path for this operation:

post /s/{space_id}/api/alerting/v2/rules/_bulk_create

Refer to Spaces for more information.

Creates up to 100 rules in a single request. Each item can include a client-supplied id. Kibana generates an identifier when id is omitted. The request succeeds with HTTP 200 even when some rules fail. Created rules are returned in rules. Failures are returned in errors. Check errors before treating the request as fully successful. To create a single rule, use POST /api/alerting/v2/rules.

[Required authorization] Route required privileges: manage_alerting-v2-rules.

Headers

  • kbn-xsrf string Required

    A required header to protect against CSRF attacks

application/json

Body

  • rules array[object] Required

    The rules to create. Must contain between 1 and 100 rules.

    At least 1 but not more than 100 elements.

    Hide rules attributes Show rules attributes object
    • artifacts array[object]

      Optional objects attached to the rule, such as a runbook or a dashboard. Each item has id, type, and data. The shape of data depends on type. For example, a runbook uses content and a dashboard uses dashboard_id. Known types are validated against that shape. Unknown types are stored when id, type, and data are present.

      Not more than 100 elements.

      Hide artifacts attributes Show artifacts attributes object
      • data object Required

        Structured artifact data.

        Additional properties are allowed.

      • id string Required

        Artifact identifier.

        Minimum length is 1, maximum length is 256.

      • type string Required

        Artifact type.

        Minimum length is 1, maximum length is 128.

    • enabled boolean

      If true (default), the rule runs on its schedule after creation. If false, the rule is saved but does not run until you enable it.

      Default value is true.

    • grouping object

      Grouping configuration.

      Additional properties are NOT allowed.

      Hide grouping attribute Show grouping attribute object
      • fields array[string] Required

        Fields to group alerts by, e.g. ["host.name", "service.name"]. Should match ES|QL GROUP BY fields.

        Not more than 16 elements. Minimum length of each is 1, maximum length of each is 256.

    • id string

      Optional rule ID. If omitted, Kibana generates one. IDs in the request must be unique.

      Minimum length is 1, maximum length is 150.

    • kind string Required

      Whether the rule creates alerts (alert) or only stores matching events (signal).

      Any of:

      Creates an alert for each matching group and tracks it until it recovers. Use this when you want to detect a problem and notify or automate a response.

      Value is alert.

      Stores each match as a rule event you can query. Alerts are not created and notifications are not sent.

      Value is signal.

    • metadata object Required

      Rule metadata.

      Additional properties are NOT allowed.

      Hide metadata attributes Show metadata attributes object
      • builder_type string

        Identifies the rule builder that authored this rule (e.g. "threshold"). Absent for rules authored directly in ES|QL.

        Maximum length is 64.

      • description string

        Human-readable description of the rule.

        Maximum length is 1024.

      • name string Required

        Rule name (must be unique within the space).

        Minimum length is 1, maximum length is 256.

      • owner string

        Owner of the rule.

        Maximum length is 256.

      • tags array[string]

        Tags for categorization, e.g. ["production", "infra"].

        At least 1 but not more than 20 elements. Minimum length of each is 1, maximum length of each is 128.

    • no_data_strategy string

      How the rule behaves when it finds no data for a group. If you omit this field or set it to none, those runs are ignored. If you set last_known_status or recover, a standalone query (query.format: standalone) must include query.no_data. A composed query (query.format: composed) uses query.base to detect whether data is present. The emit value is not accepted when creating or updating rules.

      Any of:

      Keeps the alert's last status when the rule finds no data.

      Value is last_known_status.

      Not accepted when creating or updating rules. Do not send this value.

      Value is emit.

      Marks the alert inactive the first time the rule finds no data for the alert.

      Value is recover.

      Ignores runs where the rule finds no data.

      Value is none.

    • query object Required

      Detection query configuration.

      One of:
    • recovery_strategy string

      The condition that marks an alert recovered. If omitted or set to none, recovery is disabled: the alert stays active even after the breach query stops returning matches, and state_transition.recovering_count / recovering_timeframe are not allowed. Set to no_breach to recover when the breach query stops returning matches. Set to query only when you also provide query.recovery.

      Any of:

      Recovers an alert when the breach query no longer returns matches.

      Value is no_breach.

      Recovers an alert when a separate recovery query matches. Requires query.recovery.

      Value is query.

      The rule never marks an alert as recovered, even after the breach query stops returning matches.

      Value is none.

    • schedule object Required

      Execution schedule configuration.

      Additional properties are NOT allowed.

      Hide schedule attributes Show schedule attributes object
      • every string Required

        Execution interval, e.g. 1m, 5m, 1h.

        Maximum length is 32.

      • lookback string

        Lookback window for the query, e.g. 5m, 1h. Can also be expressed in ES|QL.

        Maximum length is 32.

    • state_transition object | null

      Consecutive-match or time requirements before an alert becomes active or inactive. Applies only when kind is alert.

      Additional properties are NOT allowed.

      Hide state_transition attributes Show state_transition attributes object | null
      • pending_count integer

        Number of consecutive matches required before the alert becomes active.

        Minimum value is 0, maximum value is 1000.

      • pending_operator string

        The operator that combines pending_count and pending_timeframe. AND requires both. OR requires either.

        Values are AND or OR.

      • pending_timeframe string

        Time window used with pending_count, for example 5m or 15m.

        Maximum length is 32.

      • recovering_count integer

        Number of consecutive recoveries required before the alert becomes inactive.

        Minimum value is 0, maximum value is 1000.

      • recovering_operator string

        The operator that combines recovering_count and recovering_timeframe. AND requires both. OR requires either.

        Values are AND or OR.

      • recovering_timeframe string

        Time window used with recovering_count, for example 5m or 15m.

        Maximum length is 32.

    • time_field string

      Document field used as the event time when applying the lookback window. Defaults to @timestamp.

      Minimum length is 1, maximum length is 128. Default value is @timestamp.

Responses

  • 200 application/json

    Created rules are returned in rules. Failures are returned in errors.

    Hide response attributes Show response attributes object
    • errors array[object] Required

      Errors for rules that could not be created. Each entry includes the rule id and the error. Empty when every requested rule was created.

      Hide errors attributes Show errors attributes object
      • error object Required
        Hide error attributes Show error attributes object
        • code string Required

          Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

        • details object

          Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

          Additional properties are allowed.

        • message string Required

          A readable explanation of the error. The wording can change without notice. Do not parse this field.

      • id string Required

        The identifier of the resource that failed.

    • rules array[object] Required

      Rules that were created. Rules listed in errors are not included.

      Hide rules attributes Show rules attributes object
      • artifacts array[object]

        Optional objects attached to the rule, such as a runbook or a dashboard. Each item has id, type, and data. The shape of data depends on type. For example, a runbook uses content and a dashboard uses dashboard_id. Known types are validated against that shape. Unknown types are stored when id, type, and data are present.

        Not more than 100 elements.

        Hide artifacts attributes Show artifacts attributes object
        • data object Required

          Structured artifact data.

          Additional properties are allowed.

        • id string Required

          Artifact identifier.

          Minimum length is 1, maximum length is 256.

        • type string Required

          Artifact type.

          Minimum length is 1, maximum length is 128.

      • created_at string Required

        ISO timestamp when the rule was created.

      • created_by string | null Required

        User who created the rule.

      • enabled boolean Required

        Whether the rule is enabled.

      • grouping object

        Grouping configuration.

        Additional properties are NOT allowed.

        Hide grouping attribute Show grouping attribute object
        • fields array[string] Required

          Fields to group alerts by, e.g. ["host.name", "service.name"]. Should match ES|QL GROUP BY fields.

          Not more than 16 elements. Minimum length of each is 1, maximum length of each is 256.

      • id string Required

        Unique rule identifier.

      • kind string Required

        Whether the rule creates alerts (alert) or only stores matching events (signal).

        Any of:

        Creates an alert for each matching group and tracks it until it recovers. Use this when you want to detect a problem and notify or automate a response.

        Value is alert.

        Stores each match as a rule event you can query. Alerts are not created and notifications are not sent.

        Value is signal.

      • metadata object Required

        Additional properties are NOT allowed.

        Hide metadata attributes Show metadata attributes object
        • builder_type string

          Identifies the rule builder that authored this rule (e.g. "threshold"). Absent for rules authored directly in ES|QL.

          Maximum length is 64.

        • description string

          Human-readable description of the rule.

          Maximum length is 1024.

        • name string Required

          Rule name (must be unique within the space).

          Minimum length is 1, maximum length is 256.

        • owner string

          Owner of the rule.

          Maximum length is 256.

        • tags array[string]

          Tags for categorization, e.g. ["production", "infra"].

          At least 1 but not more than 20 elements. Minimum length of each is 1, maximum length of each is 128.

        • version integer Required

          Monotonically increasing integer number representing a rule configuration version, incremented on every change. Used on generated rule events as rule.version.

          Minimum value is 1, maximum value is 9007199254740991.

      • no_data_strategy string

        How the rule behaves when it finds no data for a group. If you omit this field or set it to none, those runs are ignored. If you set last_known_status or recover, a standalone query (query.format: standalone) must include query.no_data. A composed query (query.format: composed) uses query.base to detect whether data is present. The emit value is not accepted when creating or updating rules.

        Any of:

        Keeps the alert's last status when the rule finds no data.

        Value is last_known_status.

        Not accepted when creating or updating rules. Do not send this value.

        Value is emit.

        Marks the alert inactive the first time the rule finds no data for the alert.

        Value is recover.

        Ignores runs where the rule finds no data.

        Value is none.

      • query object Required

        Detection query configuration.

        One of:
      • recovery_strategy string

        The condition that marks an alert recovered. If omitted or set to none, recovery is disabled: the alert stays active even after the breach query stops returning matches, and state_transition.recovering_count / recovering_timeframe are not allowed. Set to no_breach to recover when the breach query stops returning matches. Set to query only when you also provide query.recovery.

        Any of:

        Recovers an alert when the breach query no longer returns matches.

        Value is no_breach.

        Recovers an alert when a separate recovery query matches. Requires query.recovery.

        Value is query.

        The rule never marks an alert as recovered, even after the breach query stops returning matches.

        Value is none.

      • schedule object Required

        Execution schedule configuration.

        Additional properties are NOT allowed.

        Hide schedule attributes Show schedule attributes object
        • every string Required

          Execution interval, e.g. 1m, 5m, 1h.

          Maximum length is 32.

        • lookback string

          Lookback window for the query, e.g. 5m, 1h. Can also be expressed in ES|QL.

          Maximum length is 32.

      • state_transition object | null

        Consecutive-match or time requirements before an alert becomes active or inactive. Applies only when kind is alert.

        Additional properties are NOT allowed.

        Hide state_transition attributes Show state_transition attributes object | null
        • pending_count integer

          Number of consecutive matches required before the alert becomes active.

          Minimum value is 0, maximum value is 1000.

        • pending_operator string

          The operator that combines pending_count and pending_timeframe. AND requires both. OR requires either.

          Values are AND or OR.

        • pending_timeframe string

          Time window used with pending_count, for example 5m or 15m.

          Maximum length is 32.

        • recovering_count integer

          Number of consecutive recoveries required before the alert becomes inactive.

          Minimum value is 0, maximum value is 1000.

        • recovering_operator string

          The operator that combines recovering_count and recovering_timeframe. AND requires both. OR requires either.

          Values are AND or OR.

        • recovering_timeframe string

          Time window used with recovering_count, for example 5m or 15m.

          Maximum length is 32.

      • time_field string

        Document field used as the event time when applying the lookback window. Defaults to @timestamp.

        Minimum length is 1, maximum length is 128. Default value is @timestamp.

      • updated_at string Required

        ISO timestamp when the rule was last updated.

      • updated_by string | null Required

        User who last updated the rule.

      • version string

        The saved object version token of the rule, used for optimistic concurrency control.

  • 400 application/json

    Indicates an invalid schema or parameters.

    Hide response attributes Show response attributes object
    • code string Required

      Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

    • details object

      Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

      Additional properties are allowed.

    • error string Required

      A short human-readable summary of the error category (e.g., "Not Found", "Bad Request"). Subject to change without notice. Do not parse or rely on its content.

    • message string Required

      A readable explanation of the error. The wording can change without notice. Do not parse this field.

  • 401 application/json

    Indicates the request was not authenticated.

    Hide response attributes Show response attributes object
    • code string Required

      Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

    • details object

      Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

      Additional properties are allowed.

    • error string Required

      A short human-readable summary of the error category (e.g., "Not Found", "Bad Request"). Subject to change without notice. Do not parse or rely on its content.

    • message string Required

      A readable explanation of the error. The wording can change without notice. Do not parse this field.

  • 403 application/json

    Indicates the user does not have the required privileges to perform the request.

    Hide response attributes Show response attributes object
    • code string Required

      Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

    • details object

      Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

      Additional properties are allowed.

    • error string Required

      A short human-readable summary of the error category (e.g., "Not Found", "Bad Request"). Subject to change without notice. Do not parse or rely on its content.

    • message string Required

      A readable explanation of the error. The wording can change without notice. Do not parse this field.

  • 500 application/json

    Indicates an unexpected server-side error.

    Hide response attributes Show response attributes object
    • code string Required

      Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

    • details object

      Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

      Additional properties are allowed.

    • error string Required

      A short human-readable summary of the error category (e.g., "Not Found", "Bad Request"). Subject to change without notice. Do not parse or rely on its content.

    • message string Required

      A readable explanation of the error. The wording can change without notice. Do not parse this field.

  • 503 application/json

    Indicates the alerting engine is disabled by the alerting:v2:enabled advanced setting.

    Hide response attributes Show response attributes object
    • code string Required

      Stable error code you can branch on, for example INVALID_SCHEDULE or RULE_ALREADY_EXISTS.

    • details object

      Optional extra information about the error, for example field validation issues or the rule_id when that ID already exists.

      Additional properties are allowed.

    • error string Required

      A short human-readable summary of the error category (e.g., "Not Found", "Bad Request"). Subject to change without notice. Do not parse or rely on its content.

    • message string Required

      A readable explanation of the error. The wording can change without notice. Do not parse this field.

POST /api/alerting/v2/rules/_bulk_create
curl \
 --request POST 'https://<KIBANA_URL>/api/alerting/v2/rules/_bulk_create' \
 --header "Authorization: $API_KEY" \
 --header "Content-Type: application/json" \
 --header "kbn-xsrf: true" \
 --data '{
  "rules": [
    {
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high",
        "tags": [
          "production",
          "infra"
        ]
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp"
    },
    {
      "enabled": false,
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "id": "rule-disabled",
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high (disabled)",
        "tags": [
          "production",
          "infra"
        ]
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp"
    }
  ]
}'
Request example
{
  "rules": [
    {
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high",
        "tags": [
          "production",
          "infra"
        ]
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp"
    },
    {
      "enabled": false,
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "id": "rule-disabled",
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high (disabled)",
        "tags": [
          "production",
          "infra"
        ]
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp"
    }
  ]
}
Response examples (200)
{
  "errors": [],
  "rules": [
    {
      "created_at": "2026-01-15T12:00:00.000Z",
      "created_by": "elastic",
      "enabled": true,
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "id": "rule-1",
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high",
        "tags": [
          "production",
          "infra"
        ],
        "version": 1
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp",
      "updated_at": "2026-01-15T12:00:00.000Z",
      "updated_by": "elastic",
      "version": "WzAsMV0="
    },
    {
      "created_at": "2026-01-15T12:00:00.000Z",
      "created_by": "elastic",
      "enabled": false,
      "grouping": {
        "fields": [
          "host.name"
        ]
      },
      "id": "rule-disabled",
      "kind": "alert",
      "metadata": {
        "description": "Alerts when average CPU usage exceeds a threshold.",
        "name": "Host CPU high (disabled)",
        "tags": [
          "production",
          "infra"
        ],
        "version": 1
      },
      "query": {
        "breach": {
          "query": "FROM metrics-* | WHERE host.cpu.usage > 0.9 | STATS avg_cpu = AVG(host.cpu.usage) BY host.name"
        },
        "format": "standalone"
      },
      "recovery_strategy": "no_breach",
      "schedule": {
        "every": "1m",
        "lookback": "5m"
      },
      "state_transition": {
        "pending_count": 1,
        "recovering_count": 1
      },
      "time_field": "@timestamp",
      "updated_at": "2026-01-15T12:00:00.000Z",
      "updated_by": "elastic",
      "version": "WzAsMV0="
    }
  ]
}
Response examples (400)
{
  "code": "BAD_REQUEST",
  "details": {
    "errors": {
      "rules": [
        "Required"
      ]
    }
  },
  "error": "Bad Request",
  "message": "rules: Required"
}
Response examples (401)
{
  "code": "UNAUTHORIZED",
  "error": "Unauthorized",
  "message": "Authentication required to access this API."
}
Response examples (403)
{
  "code": "FORBIDDEN",
  "error": "Forbidden",
  "message": "The current user does not have the required privileges for this request."
}
Response examples (500)
{
  "code": "INTERNAL_SERVER_ERROR",
  "error": "Internal Server Error",
  "message": "An unexpected error occurred."
}
Response examples (503)
{
  "code": "ALERTING_DISABLED",
  "error": "Service Unavailable",
  "message": "Alerting is disabled."
}