> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook

> Receive external HTTP requests to start or resume workflow executions

The **Webhook** node turns your workflow into an HTTP endpoint accessible from any external system. It enables two main flows: **starting new executions** and **resuming existing executions** — all through a simple HTTP call.

Think of this node as the front door of your workflow: external systems knock (send an HTTP request), and your flow decides what to do with what they bring.

<Note>
  The Webhook node is available in both **Tools** and **Skills**. Only **one Webhook node per canvas** is allowed.
</Note>

***

## Operation modes

The Webhook node operates in two modes, automatically determined by the presence of the `executionId`:

### Start new execution

When the request **does not include** an `executionId`, the webhook creates a new workflow execution from scratch.

**Use case:** An external system (CRM, ERP, payment gateway) needs to trigger an automated process in Jelou.

```bash theme={null}
curl -X POST https://brain.jelou.ai/v1/webhook/{webhookId} \
  -H "Content-Type: application/json" \
  -d '{"event": "new_order", "customer": "12345"}'
```

### Resume existing execution

When the request **includes** an `executionId`, the webhook resumes an execution that was paused waiting for an external response.

**Use case:** A payment gateway notifies that the payment was processed, and the flow should continue where it left off.

```bash theme={null}
curl -X POST https://brain.jelou.ai/v1/webhook/{webhookId} \
  -H "Content-Type: application/json" \
  -d '{"executionId": "abc-123", "status": "paid"}'
```

<Tip>
  The `executionId` can be sent in the **body** (using the dot notation path configured in the node) or as a **query param** `executionId`. This allows using HTTP methods like GET that don't have a body.
</Tip>

***

## Configuration

### Variable name

Define the name under which webhook data will be stored within the `$webhook` variable. Data received by the request will be available at `$webhook.<variableName>`. For example, if you define `myWebhook`, you can access the body via `{{$webhook.myWebhook.body}}`, headers via `{{$webhook.myWebhook.headers}}`, etc.

### HTTP Method

Select which HTTP methods the webhook accepts. Supports GET, POST, PUT, PATCH, and DELETE.

<Note>
  For methods without a body (like GET), the `executionId` for resuming must be sent as a query param: `?executionId=abc-123`.
</Note>

### Resume multiple times (oneTimeOnly)

By default, an execution can be resumed **more than once** by the webhook. If you need to restrict this — for example, in payment integrations where a confirmation should only be processed once — you can enable the **"Resume only once"** option in advanced settings.

| Setting                            | Behavior                                                                     |
| :--------------------------------- | :--------------------------------------------------------------------------- |
| **oneTimeOnly disabled** (default) | The webhook can resume the same execution multiple times                     |
| **oneTimeOnly enabled**            | The webhook only resumes the execution once; subsequent attempts are ignored |

***

## `$webhook` variable

When a request reaches the Webhook node, all request information becomes available through the `$webhook` variable. It works similarly to `$memory` and `$context`.

| Property                                 | Description                  | Example                                      |
| :--------------------------------------- | :--------------------------- | :------------------------------------------- |
| `$webhook.<variableName>.body`           | HTTP request body            | `{"event": "payment_success", "amount": 50}` |
| `$webhook.<variableName>.headers`        | Request headers              | `{"content-type": "application/json"}`       |
| `$webhook.<variableName>.query`          | URL query params             | `{"ref": "campaign-123"}`                    |
| `$webhook.<variableName>.method`         | HTTP method used             | `POST`                                       |
| `$webhook.<variableName>.mode`           | Execution mode               | `new` or `resume`                            |
| `$webhook.<variableName>.executionId`    | Current execution ID         | `exec-abc-123`                               |
| `$webhook.<variableName>.isNewExecution` | Whether it's a new execution | `true` or `false`                            |

### Usage example in the flow

Assuming you defined `myWebhook` as the variable name, you can use the properties in any subsequent node:

```
# In a Conditional node
{{$webhook.myWebhook.body.event}} == "payment_success"

# In a Text node
The payment of {{$webhook.myWebhook.body.amount}} was processed successfully.

# In an API node
Authorization: {{$webhook.myWebhook.headers.authorization}}
```

***

## Webhook in Skills

The Webhook node is available in Skills, allowing conversational flows to be triggered or resumed by external events.

### Considerations for Skills

<AccordionGroup>
  <Accordion title="New executions in Skills">
    To start a new Skill execution via webhook, the request **must include the user identifier** (e.g., phone number for WhatsApp). This is needed so the Skill can send messages to the user through the corresponding channel.

    ```bash theme={null}
    curl -X POST https://brain.jelou.ai/v1/webhook/{webhookId} \
      -H "Content-Type: application/json" \
      -d '{"phone": "+593999999999", "event": "reminder"}'
    ```
  </Accordion>

  <Accordion title="Resuming executions in Skills">
    To resume an existing execution, only the `executionId` is needed. The system already has the user context from the original execution.
  </Accordion>

  <Accordion title="Platform restrictions">
    On platforms like WhatsApp, if there is **no active session** (24-hour window) between the user and the bot, the webhook won't be able to send messages directly. In these cases, you can use an **HSM node** within the flow to send an approved template that reopens the conversational window.
  </Accordion>

  <Accordion title="Versioning">
    The webhook always executes the **latest published version** of the Skill. If there is more than one bot from the same channel connected to the project, the most recent one is used.
  </Accordion>

  <Accordion title="Inheritance in child workflows">
    When a child Skill inherits webhooks from its parent Skill, if the child Skill receives a request, it **overwrites** the parent flow's webhook data. The `$webhook` data propagates to child executions (internal Skill nodes).
  </Accordion>
</AccordionGroup>

***

## Testing (Draft)

To test the webhook during development (before publishing), the node generates a test URL with the `/test` suffix:

```
# Production URL
https://brain.jelou.ai/v1/webhook/{webhookId}

# Test URL (draft)
https://brain.jelou.ai/v1/webhook/{webhookId}/test
```

The `/test` URL executes the current draft of the workflow, allowing you to iterate without affecting the published version.

<Warning>
  In Skills, draft testing is done through the **Skill Tester**. User parameters configured in the Skill Tester also apply when invoking the webhook in test mode.
</Warning>

***

## Backward compatibility

Webhooks created before this update **continue to work without changes**. The improvements only apply going forward:

* **Existing webhooks** keep their legacy configuration, including the "variable" field that stored data in `$context`.
* **New webhooks** always store information in the new `$webhook` entity, offering a richer and more consistent structure.

<Info>
  For legacy webhooks that had a context variable configured, the variable configuration component will still be shown for backward compatibility. In new webhooks, this field does not appear since data is always stored in `$webhook`.
</Info>

***

## Common use cases

<CardGroup cols={2}>
  <Card title="Payment notifications" icon="credit-card">
    Receive confirmations from gateways like Stripe or MercadoPago and resume the purchase flow.
  </Card>

  <Card title="CRM integrations" icon="building">
    Trigger automated flows when a record is created or updated in your CRM.
  </Card>

  <Card title="E-commerce events" icon="cart-shopping">
    Process events like cart abandonment, order shipment, or returns.
  </Card>

  <Card title="IoT automations" icon="microchip">
    Receive data from sensors or devices to trigger alert or processing flows.
  </Card>
</CardGroup>
