﻿---
title: waitForApproval
description: Reference for the waitForApproval step, which pauses a workflow until a human approves or rejects the request in Kibana or through an external resume link.
url: https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/steps/wait-for-approval
products:
  - Elastic Cloud Enterprise
  - Elastic Cloud Hosted
  - Elastic Cloud Serverless
  - Elastic Cloud on Kubernetes
  - Elastic Stack
  - Kibana
applies_to:
  - Elastic Cloud Serverless: Preview
  - Elastic Stack: Planned
---

# waitForApproval
The `waitForApproval` step pauses workflow execution until a human approves or rejects the request. Use it when the decision is yes or no. The step returns `approved: true` or `false` and renders approve/reject controls in Kibana and in external notifications. Approvers respond from the workflow execution view, the [Inbox app](/elastic/docs-content/tree/main/explore-analyze/workflows/authoring-techniques/human-in-the-loop#workflows-hitl-inbox), or an external notification.
For free-form or multi-field input, use [`waitForInput`](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/steps/wait-for-input) instead. For the end-to-end human-in-the-loop pattern, refer to [Human-in-the-loop](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/authoring-techniques/human-in-the-loop).
**Schema convention.** In each schema table on this page, the `Location` column indicates where each parameter sits in the YAML:
- `top level`: Alongside `type` and `name`, at the top of the step or trigger definition.
- ``with``: Inside the step's `with:` block.
- ``on``: Inside the trigger's `on:` block.


## Parameters


| Parameter      | Location  | Type     | Required | Description                                                                                                                                                         |
|----------------|-----------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name`         | top level | string   | Yes      | Unique step identifier.                                                                                                                                             |
| `type`         | top level | string   | Yes      | Must be `waitForApproval`.                                                                                                                                          |
| `timeout`      | top level | duration | No       | How long the step waits for a decision. Format: number + unit (`ms`/`s`/`m`/`h`/`d`/`w`). Defaults to `24h`. If no one responds before the timeout, the step fails. |
| `message`      | `with`    | string   | No       | Markdown message displayed to approvers.                                                                                                                            |
| `approveLabel` | `with`    | string   | No       | Label for the approve action. Defaults to `Approve`.                                                                                                                |
| `rejectLabel`  | `with`    | string   | No       | Label for the reject action. Defaults to `Decline`.                                                                                                                 |
| `channels`     | `with`    | object   | No       | External notification channels that send approve/reject links. Responders can act without signing in to Kibana. See [External channels](#external-channels).        |


## External channels

Use `with.channels` to notify approvers outside Kibana. Slack is the only built-in channel. Notifications include one-click approve and reject links. Responders can act without signing in to Kibana.

| Channel key | Connector type          | Required fields                                         | Notes                                                     |
|-------------|-------------------------|---------------------------------------------------------|-----------------------------------------------------------|
| `slack`     | Slack webhook (`slack`) | `connector-id`                                          | Posts to the channel configured on the webhook connector. |
| `slack_api` | Slack API (`slack_api`) | `connector-id`, `channels` (array of Slack channel IDs) | Posts approve/reject buttons to the listed channels.      |

Slack content comes from the step-level `with.message` plus the generated approve and reject actions.
<warning>
  External channels send public, short-lived resume links. Don't use them for destructive, production-impacting, or hard-to-reverse workflows.
</warning>

To turn off external resume, set both `hitlExternalResume.enabled` keys in `kibana.yml` (both default to `true`). For the exact settings, refer to [Human-in-the-loop](/elastic/docs-content/tree/main/explore-analyze/workflows/authoring-techniques/human-in-the-loop#workflows-hitl-external-channels).

## Output

After someone responds, the step output has this shape:
```yaml
response:
  approved: true   
respondedBy: "..." 
```

Downstream steps typically gate on `{{ steps.<step_name>.output.response.approved }}`.

## Execution state

While waiting for a response, the step stays in the `WAITING_FOR_INPUT` state. How the step resolves depends on the response it receives:
- **Approve** finishes the step successfully with `response.approved: true`.
- **Decline** also finishes the step successfully, but with `response.approved: false`. Declining does not fail the step or cancel the workflow, so you must branch on the decision (for example, with an `if` guard on `output.response.approved`) to stop downstream work.
- **No response** fails the step. By default, the step times out after `24h`, whether or not you configure an external channel. Override this with a top-level `timeout`.


## Example: Approve host isolation

```yaml
- name: request_approval
  type: waitForApproval
  timeout: 24h
  with:
    message: "Approve isolation for {{ event.alerts[0].host.name }}?"
    approveLabel: Approve
    rejectLabel: Decline
    channels:
      slack:
        connector-id: my-slack-webhook-connector
      slack_api:
        connector-id: my-slack-api-connector
        channels: ["C0123456789"]

- name: isolate
  type: http
  if: "steps.request_approval.output.response.approved : true"
  connector-id: "edr-connector"
  with:
    method: "POST"
    url: "https://edr.example.com/isolate"
    body:
      host: "{{ event.alerts[0].host.name }}"
```


## Related

- [Human-in-the-loop pattern](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/authoring-techniques/human-in-the-loop): Inbox, external resume, and design guidance.
- [`waitForInput` step](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/steps/wait-for-input): Collect structured input with a custom JSON Schema.
- [Flow control steps](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/steps/flow-control-steps): Other flow-control types you'll often combine with approval gates.
- [If step](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/explore-analyze/workflows/steps/if): Typical gate around the post-approval action.