# Run a flow through a webhook

import { Steps, TabItem, Tabs } from "@astrojs/starlight/components"

A **Webhook** trigger starts a flow when an external system sends an HTTP request to a Mindflow URL. You choose
asynchronous or synchronous mode, optionally require an API key, and can return a custom HTTP response with a
**Webhook response** step. Screenshots on this page show the Webhook trigger Settings and Auth tabs so you can match
the labels in Studio.

## When to use

- An external ticketing system, SIEM, form, or middleware must start a flow over HTTPS.
- You need an immediate HTTP acknowledgment (async) or a response body from the flow (sync).
- Prefer [Run a flow from an AI··Room](../run-a-flow-from-an-ai-room/) when operators should start the flow from chat.
- Prefer [Run a flow through email](../run-flow-through-emails/) when the source is inbound email.
- Prefer [Call a flow](../../control-flow-execution/call-a-flow/) when one Mindflow flow should start another inside
  Studio.

Before you begin, you need permission to create and deploy flows in the environment. Deploy the flow before callers
rely on the webhook URL in production.

## Guide

### Add a Webhook trigger

A **Webhook** is the trigger that exposes HTTPS endpoints for the flow. Studio shows copyable URLs after you add the
step.

<ol>
<li>

**Open the flow.** Create or open the flow in the designer.

</li>
<li>

**Add a step manually.** On an empty canvas, choose **Add a step manually**.

<div class="docs-screenshot-compact">

![Empty designer with Add a step manually and Ask AI to generate steps cards](./assets/empty-designer-add-step-manually-ask.png)

</div>

</li>
<li>

**Choose Webhook.** In the step catalog, open **Triggers**, then choose **Webhook**.

<div class="docs-screenshot-compact">

![Add a step catalog Triggers section with Webhook, Emailhook, Chathook, Flowhook, Formhook, and Scheduler](./assets/add-step-catalog-triggers-section-webhook.png)

</div>

</li>
<li>

**Rename and describe the step.** Rename the Webhook step and fill a description so the designer shows why this trigger
exists.

</li>
<li>

**Open Settings.** On the Webhook step, open the **Settings** tab. Copy **Asynchronous (TLS)** or **Synchronous (TLS)**
from the read-only fields. When mTLS is enabled for your environment, Studio also shows **Asynchronous (MTLS)** and
**Synchronous (MTLS)**.

<div class="docs-screenshot-compact">

![Webhook Trigger Settings with Asynchronous (TLS) and Synchronous (TLS) copyable URLs and Webhook headers callout](./assets/webhook-trigger-settings-asynchronous-tls.png)

</div>

</li>
</ol>
### Choose asynchronous or synchronous mode

**Asynchronous** returns an HTTP response as soon as Mindflow accepts the request, without waiting for the flow to
finish. **Synchronous** waits for the flow (and an optional **Webhook response** step) before returning.

Copy the matching URL from Settings. Studio shows the query-param route (`…/run-async-qp` or `…/run-sync-qp`) with the
trigger id in the path. Hostnames come from your tenant (for example `webhook-….mindflow.dev`).

```bash title="Asynchronous (TLS) example"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/{trigger-id}/steps/start/run-async-qp"
```

```bash title="Synchronous (TLS) example"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/{trigger-id}/steps/start/run-sync-qp"
```

:::note
**mTLS** uses a separate hostname when your environment has mutual TLS enabled. If **Security protocol** or the mTLS
URL fields are missing, contact Mindflow support.
:::

### Secure the webhook with an API key

Without an API key, any caller who knows the URL can start the flow. On the canvas, the Webhook step shows security
status badges (for example an open lock when there is no API key protection). On **Auth**, generate a key so callers
must send it—the open-lock badge clears once a key is configured.

<div class="docs-screenshot-compact">

![Webhook trigger step on the canvas with security badges and tooltip Webhook has no key protection](./assets/webhook-trigger-security-badges.png)

</div>

<ol>
<li>

**Open Auth.** On the Webhook step, open the **Auth** tab.

<div class="docs-screenshot-compact">

![Webhook Trigger Auth tab with No API key means this webhook is open and Generate API key](./assets/webhook-trigger-auth-tab-no-api.png)

</div>

</li>
<li>

**Generate API key.** Choose **Generate API key**. Copy the key and store it with your caller. Use **Rotate** or
**Delete** from the key menu when you need to replace or remove it.

<div class="docs-screenshot-compact">

![Webhook Trigger Auth tab with masked API key, reveal and copy controls, and Webhook headers callout](./assets/webhook-trigger-auth-tab-masked-api.png)

</div>

</li>
</ol>
### Send the API key and flow deployment id

Callers must identify the flow and, when a key exists, authenticate. Prefer headers over query parameters when your
caller supports them.

Send the key as `x-api-key`. Use a non-`-qp` path URL when the trigger id is already in the path:

```bash title="API key header"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/{trigger-id}/steps/start/run-async" \
  -H "x-api-key: YOUR_API_KEY"
```

Append `apikey` on the query-param route. Prefer headers when you can; query keys can appear in proxy logs.

```bash title="API key query parameter"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/{trigger-id}/steps/start/run-async-qp?apikey=YOUR_API_KEY"
```

:::note
Query-parameter auth remains supported for callers that cannot set headers (for example some Atlassian Jira webhook
configurations).
:::

The Settings copy fields already include the trigger id in `/playbooks/{trigger-id}/…`. That is the usual path for the
URLs Studio shows.

```bash title="Trigger id in path"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/{trigger-id}/steps/start/run-async" \
  -H "x-api-key: YOUR_API_KEY"
```

Use the header-only URL and send the flow deployment id as
`x-mindflow-flow-deployment-id` (or the legacy alias `x-mindflow-playbook-id`):

```bash title="Flow deployment id header"
curl "https://webhook-{tenant}.mindflow.dev/playbooks/steps/start/run-async" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "x-mindflow-flow-deployment-id: {flow-deployment-id}"
```

:::caution
Studio’s **Webhook headers** callout may show `x-flow-deployment-id`. Callers must use
`x-mindflow-flow-deployment-id` or `x-mindflow-playbook-id` — those are the headers the webhook runtime accepts.
:::

### Return a custom HTTP response

**Webhook response** sets the status code, headers, and body for a **synchronous** webhook call. Place it where the
flow should reply. The flow can continue after the response; later steps keep running asynchronously.

<ol>
<li>

**Add Webhook response.** Open **Add a step**, choose **Flow**, then **Webhook response**.

<div class="docs-screenshot-compact">

![Add a step Flow section with Webhook response highlighted](./assets/add-step-flow-section-webhook-response.png)

</div>

</li>
<li>

**Configure the response.** On **Input**, set **Status Code**, optional **Headers**, and **Body** (JSON, Text, or
XML). Use data pills for dynamic values.

<div class="docs-screenshot-compact">

![Webhook response step with status code, headers, and body fields](./assets/webhook-response-step-status-code-headers.png)

</div>

</li>
<li>

**Call the synchronous URL.** Use **Synchronous (TLS)** (or mTLS) from Webhook Settings — not the asynchronous URL.

<div class="docs-screenshot-compact">

![Webhook Settings highlighting the synchronous endpoint used with Webhook response](./assets/webhook-settings-highlighting-synchronous.png)

</div>

</li>
</ol>
:::note
The flow must reach **Webhook response** within **25 seconds**. Otherwise Mindflow cannot return your custom response
and the synchronous call fails. On non-webhook triggers, **Webhook response** is ignored and the run continues.
:::

### Limit callers by IP

On the Webhook step, open **Advanced** and add **Allowed IPs** when only specific networks should call this endpoint.
Organization-level allowlists apply as well — see [Restrict webhook callers with an IP allowlist](../ip-whitelisting/).

## Example

A SOC platform posts a new alert JSON to Mindflow. The flow **Ingest SIEM alert** starts with a Webhook named
**Receive SIEM alert**, uses an API key in `x-api-key`, and runs asynchronously so the SIEM gets an immediate
acknowledgment while enrichment continues in later steps.

For a caller that needs a custom body back (for example a chatbot middleware), use the synchronous URL and a
**Webhook response** step that returns status `200` and a short text or JSON body within 25 seconds.

<details>
<summary>Authorizer flow pattern</summary>

When a vendor sends a token you must verify before the real automation runs, put validation on a front webhook flow,
then call the destination flow only after the check passes.

<ol>
<li>

**Receive the vendor request.** Start with a Webhook (often synchronous).

<div class="docs-screenshot-compact">

![Authorizer flow overview with webhook entry and security check before forwarding](./assets/authorizer-flow-overview-webhook-entry-security.png)

</div>

</li>
<li>

**Validate the token.** Call the vendor API (for example a Google OAuth token check).

<div class="docs-screenshot-compact">

![Authorizer flow validating a Google token before continuing](./assets/authorizer-flow-validating-google-token-before.png)

</div>

</li>
<li>

**Continue or reject.** On success, start the destination flow (for example with **Call a flow**). On failure, return
an error with **Webhook response**.

<div class="docs-screenshot-compact">

![Authorizer flow branching to failure response or starting the destination subflow](./assets/authorizer-flow-branching-failure-response.png)

</div>

</li>
</ol>
</details>

## Keep in mind

- Deploy the flow before external systems depend on the webhook URL.
- Supported HTTP methods include **GET**, **POST**, and **PUT**.
- Prefer `x-api-key` and `x-mindflow-flow-deployment-id` headers over query parameters when the caller can set headers.
- For network-level control, combine webhook **Allowed IPs** with the organization allowlist — see
  [Restrict webhook callers with an IP allowlist](../ip-whitelisting/).

## Related

[Trigger your flow](../) ·
[Restrict webhook callers with an IP allowlist](../ip-whitelisting/) ·
[Run a flow from an AI··Room](../run-a-flow-from-an-ai-room/) ·
[Manage version and deployments](../../../operate/manage-version-and-deployments/)
