---
type: api
title: Create an action policy
description: **Spaces method and path for this operation:**
url: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/kibana/operation/operation-post-alerting-v2-action-policies
resource: https://www.elastic.co/elastic/docs-builder/docs/4371/api/doc/kibana/operation/operation-post-alerting-v2-action-policies
products:
  - Kibana
---

# Create an action policy

Availability: 9.5+

- Server: `https://{kibana_url}`

## Paths

- `POST` `/api/alerting/v2/action_policies`
- `POST` `/s/{space_id}/api/alerting/v2/action_policies`

- [Api key auth](/elastic/docs-builder/docs/4371/api/doc/kibana/authentication#apikeyauth)
- [Basic auth](/elastic/docs-builder/docs/4371/api/doc/kibana/authentication#basicauth)

## Description

Refer to [Spaces](https://www.elastic.co/docs/deploy-manage/manage-spaces) for more information.

Creates an action policy with a server-generated identifier. To create or replace an action policy with a client-supplied identifier, use PUT /api/alerting/v2/action_policies/{id}/.<br/><br/>[Required authorization] Route required privileges: manage_alerting-v2-action-policies AND read_alerting-v2-rules.

## Request Body

`application/json`

- `description` (string · min: 1 · max: 1024) — optional
  A description of the action policy. Absent when the policy has none; send `null` on PATCH to clear it.
- `destinations` ([] union  · min: 1 · max: 10) — required
  The list of destinations. At least one is required.
  - **Kibana_HTTP_APIs_alerting_workflow_action_policy_destination**
    - `id` (string · min: 1 · max: 150) — required
      The workflow identifier.
    - `type` (enum) — required
      The destination type.
      Values: `workflow`
- `grouping` (union) — optional
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_per_alert** (`mode: per_alert`)
    one notification per alert lifecycle (default).
    - `mode` (enum) — required
      Values: `per_alert`
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_all** (`mode: all`)
    a single notification for all matching alerts.
    - `mode` (enum) — required
      Values: `all`
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_per_field** (`mode: per_field`)
    group by the specified `fields`.
    - `fields` ([] string · min: 1 · max: 16) — required
      The fields alerts are grouped by. At least one is required, and no other mode accepts them.
    - `mode` (enum) — required
      Values: `per_field`
- `matcher` (object) — optional
  Selects the alerts this policy applies to. Set `tags` to match alerts from rules with those routing tags. Set `expression` to a KQL query, which will be evaluated against each alert. <br/><br/> If you set both `tags` and `expression`, an alert must match the tags and the expression for the policy to apply. At least one of `tags` and `expression` must be set, so an empty `matcher` is rejected. Omit `matcher` entirely for a catch-all policy that applies to all alerts.
  - `expression` (string · min: 1 · max: 4096) — optional
    A KQL query that's evaluated against each alert. Supported fields are: `alert_id`, `alert_status`, `group_hash`, `last_event_timestamp`, `severity`, and your rule's query output columns under `data.*` (for example, `data.host.name`). Referencing other fields won't work. Omit `matcher.expression` to match on `tags` alone.
  - `tags` ([] string · min: 1 · max: 50) — optional
    Routing tags this policy should match. The policy applies to alerts from any rule whose `metadata.routing_tags` include at least one of these tags. An empty array is not accepted. Omit `matcher.tags` to match on `matcher.expression` alone.
- `name` (string · min: 1 · max: 256) — required
  The name of the action policy.
- `throttle` (union) — optional
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_on_status_change** (`strategy: on_status_change`)
    notify only on alert status transitions (default for `per_alert`).
    - `strategy` (enum) — required
      Values: `on_status_change`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_per_status_interval** (`strategy: per_status_interval`)
    notify on transitions and at regular intervals.
    - `interval` (string · max: 32) — required
      The throttle interval duration (e.g. 5m, 1h) that sets the notification cadence.
    - `strategy` (enum) — required
      Values: `per_status_interval`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_time_interval** (`strategy: time_interval`)
    notify at regular intervals regardless of status (default for `all`/`per_field`).
    - `interval` (string · max: 32) — required
      The throttle interval duration (e.g. 5m, 1h) that sets the notification cadence.
    - `strategy` (enum) — required
      Values: `time_interval`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_every_time** (`strategy: every_time`)
    notify on every evaluation cycle (high volume).
    - `strategy` (enum) — required
      Values: `every_time`

## Responses

#### `201`

Returns the newly created action policy.

`application/json`

- `created_at` (string · pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$)
  The ISO datetime when the action policy was created.
- `created_by` ({})
  The actor who created the action policy.
  - `profile_uid` (string) — nullable
    User profile ID of the actor, or `null` when it cannot be resolved.
- `description` (string)
  A description of the action policy. Omitted when the policy has none.
- `destinations` ([] union)
  The list of destinations.
  - **Kibana_HTTP_APIs_alerting_workflow_action_policy_destination**
    - `id` (string · min: 1 · max: 150)
      The workflow identifier.
    - `type` (enum)
      The destination type.
      Values: `workflow`
- `enabled` (boolean)
  Whether the action policy is enabled.
- `grouping` (union)
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_per_alert** (`mode: per_alert`)
    one notification per alert lifecycle (default).
    - `mode` (enum)
      Values: `per_alert`
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_all** (`mode: all`)
    a single notification for all matching alerts.
    - `mode` (enum)
      Values: `all`
  - **Kibana_HTTP_APIs_alerting_action_policy_grouping_per_field** (`mode: per_field`)
    group by the specified `fields`.
    - `fields` ([] string · min: 1 · max: 16)
      The fields alerts are grouped by. At least one is required, and no other mode accepts them.
    - `mode` (enum)
      Values: `per_field`
- `id` (string)
  The unique identifier for the action policy.
- `matcher` (object)
  Selects the alerts this policy applies to. Set `tags` to match alerts from rules with those routing tags. Set `expression` to a KQL query, which will be evaluated against each alert. <br/><br/> If you set both `tags` and `expression`, an alert must match the tags and the expression for the policy to apply. At least one of `tags` and `expression` must be set, so an empty `matcher` is rejected. Omit `matcher` entirely for a catch-all policy that applies to all alerts.
  - `expression` (string · min: 1 · max: 4096)
    A KQL query that's evaluated against each alert. Supported fields are: `alert_id`, `alert_status`, `group_hash`, `last_event_timestamp`, `severity`, and your rule's query output columns under `data.*` (for example, `data.host.name`). Referencing other fields won't work. Omit `matcher.expression` to match on `tags` alone.
  - `tags` ([] string · min: 1 · max: 50)
    Routing tags this policy should match. The policy applies to alerts from any rule whose `metadata.routing_tags` include at least one of these tags. An empty array is not accepted. Omit `matcher.tags` to match on `matcher.expression` alone.
- `name` (string)
  The name of the action policy.
- `snoozed_until` (string)
  The ISO datetime until which the policy is snoozed. Omitted when the policy is not snoozed.
- `throttle` (union)
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_on_status_change** (`strategy: on_status_change`)
    notify only on alert status transitions (default for `per_alert`).
    - `strategy` (enum)
      Values: `on_status_change`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_per_status_interval** (`strategy: per_status_interval`)
    notify on transitions and at regular intervals.
    - `interval` (string · max: 32)
      The throttle interval duration (e.g. 5m, 1h) that sets the notification cadence.
    - `strategy` (enum)
      Values: `per_status_interval`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_time_interval** (`strategy: time_interval`)
    notify at regular intervals regardless of status (default for `all`/`per_field`).
    - `interval` (string · max: 32)
      The throttle interval duration (e.g. 5m, 1h) that sets the notification cadence.
    - `strategy` (enum)
      Values: `time_interval`
  - **Kibana_HTTP_APIs_alerting_action_policy_throttle_every_time** (`strategy: every_time`)
    notify on every evaluation cycle (high volume).
    - `strategy` (enum)
      Values: `every_time`
- `updated_at` (string · pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$)
  The ISO datetime when the action policy was last updated.
- `updated_by` ({})
  The actor who last updated the action policy.
  - `profile_uid` (string) — nullable
    User profile ID of the actor, or `null` when it cannot be resolved.
#### `400`

Indicates an invalid schema or parameters.

`application/json`

- `code` (string)
  Stable error code you can branch on, for example `INVALID_SCHEDULE` or `RULE_ALREADY_EXISTS`.
- `details` (map string to object)
  Optional extra information about the error, for example field validation issues or the `rule_id` when that ID already exists.
- `error` (string)
  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)
  A readable explanation of the error. The wording can change without notice. Do not parse this field.
#### `401`

Indicates the request was not authenticated.

`application/json`

- `code` (string)
  Stable error code you can branch on, for example `INVALID_SCHEDULE` or `RULE_ALREADY_EXISTS`.
- `details` (map string to object)
  Optional extra information about the error, for example field validation issues or the `rule_id` when that ID already exists.
- `error` (string)
  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)
  A readable explanation of the error. The wording can change without notice. Do not parse this field.
#### `403`

Indicates the user does not have the required privileges, or the current license does not support action policies. Creating, updating, and enabling action policies requires an active Enterprise license.

`application/json`

- `code` (string)
  Stable error code you can branch on, for example `INVALID_SCHEDULE` or `RULE_ALREADY_EXISTS`.
- `details` (map string to object)
  Optional extra information about the error, for example field validation issues or the `rule_id` when that ID already exists.
- `error` (string)
  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)
  A readable explanation of the error. The wording can change without notice. Do not parse this field.
#### `500`

Indicates an unexpected server-side error.

`application/json`

- `code` (string)
  Stable error code you can branch on, for example `INVALID_SCHEDULE` or `RULE_ALREADY_EXISTS`.
- `details` (map string to object)
  Optional extra information about the error, for example field validation issues or the `rule_id` when that ID already exists.
- `error` (string)
  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)
  A readable explanation of the error. The wording can change without notice. Do not parse this field.
#### `503`

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

`application/json`

- `code` (string)
  Stable error code you can branch on, for example `INVALID_SCHEDULE` or `RULE_ALREADY_EXISTS`.
- `details` (map string to object)
  Optional extra information about the error, for example field validation issues or the `rule_id` when that ID already exists.
- `error` (string)
  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)
  A readable explanation of the error. The wording can change without notice. Do not parse this field.
## Code Examples

#### Console

```console
POST /api/alerting/v2/action_policies
{
  "description": "Sends notifications for alerts generated by rules with the production tag.",
  "destinations": [
    {
      "id": "workflow-1",
      "type": "workflow"
    }
  ],
  "grouping": {
    "mode": "per_alert"
  },
  "matcher": {
    "tags": [
      "production"
    ]
  },
  "name": "Notify on production alerts",
  "throttle": {
    "strategy": "on_status_change"
  }
}
```

#### curl

```curl
curl -X POST "https://{kibana_url}/api/alerting/v2/action_policies" \
  -H "kbn-xsrf: true" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "Sends notifications for alerts generated by rules with the production tag.",
  "destinations": [
    {
      "id": "workflow-1",
      "type": "workflow"
    }
  ],
  "grouping": {
    "mode": "per_alert"
  },
  "matcher": {
    "tags": [
      "production"
    ]
  },
  "name": "Notify on production alerts",
  "throttle": {
    "strategy": "on_status_change"
  }
}'
```

## Response Examples

#### Newly created action policy

```json
{
  "created_at": "2026-01-15T12:00:00.000Z",
  "created_by": {
    "profile_uid": "u_elastic_0"
  },
  "description": "Sends notifications for alerts generated by rules with the production tag.",
  "destinations": [
    {
      "id": "workflow-1",
      "type": "workflow"
    }
  ],
  "enabled": true,
  "grouping": {
    "mode": "per_alert"
  },
  "id": "action-policy-1",
  "matcher": {
    "tags": [
      "production"
    ]
  },
  "name": "Notify on production alerts",
  "throttle": {
    "strategy": "on_status_change"
  },
  "updated_at": "2026-01-15T12:00:00.000Z",
  "updated_by": {
    "profile_uid": "u_elastic_0"
  }
}
```

#### Indicates an invalid schema or parameters.

```json
{
  "code": "INVALID_ACTION_POLICY_DATA",
  "details": {
    "context": "create",
    "errors": {
      "errors": [],
      "properties": {
        "name": {
          "errors": [
            "Invalid input: expected string, received undefined"
          ]
        }
      }
    }
  },
  "error": "Bad Request",
  "message": "Error validating create action policy data - name: Invalid input: expected string, received undefined"
}
```

#### Request was not authenticated

```json
{
  "code": "UNAUTHORIZED",
  "error": "Unauthorized",
  "message": "Authentication required to access this API."
}
```

#### The current license does not support action policies

```json
{
  "code": "ACTION_POLICY_LICENSE_NOT_SUPPORTED",
  "details": {
    "current_license": "basic",
    "license_status": "active",
    "required_license": "enterprise"
  },
  "error": "Forbidden",
  "message": "Action policies require an active enterprise license"
}
```

#### Caller lacks required privileges

```json
{
  "code": "FORBIDDEN",
  "error": "Forbidden",
  "message": "The current user does not have the required privileges for this request."
}
```

#### Unexpected server-side error

```json
{
  "code": "INTERNAL_SERVER_ERROR",
  "error": "Internal Server Error",
  "message": "An unexpected error occurred."
}
```

#### Alerting V2 is disabled

```json
{
  "code": "ALERTING_DISABLED",
  "error": "Service Unavailable",
  "message": "Alerting is disabled."
}
```

