# Respond to webhook

Send a custom response back to the inbound webhook caller and end the request synchronously.

## Overview

When a workflow is triggered by a **Webhook** node, the HTTP caller is held open until either the workflow finishes (default: last node's `last_output` is returned) or a Respond to webhook node fires. This node lets you craft the exact response: status code, content type, custom headers, redirects, and body.

Place it on the branch that should answer the caller — typically right before the workflow ends, or inside a specific If/else branch. Downstream nodes after it still execute (and may perform side effects), but they cannot change what the caller already received.

Without a Respond to webhook node, the Webhook trigger's `responseMode` controls what the caller sees (`lastNode` → `last_output`, `immediate` → `200 OK` before the workflow runs).

## When you can use it

A Respond node only makes sense when an HTTP caller is waiting for an answer. The editor enforces this at save time (`400`):

- **Allowed** with a **Webhook** trigger, or with a **Start** entry (a published API). In both cases a caller is held open.
- **Blocked** with a **Schedule** or **Event listener** trigger — those runs are internal, fired by the platform, so there is no caller to respond to.
- **Only one** Respond node is allowed per workflow. A second one is rejected at save.

To answer differently per case, branch with If/else *upstream* and converge on the single Respond node, or set its `statusCode`/`responseBody` from placeholders.

## Configuration

| Field | Description |
| --- | --- |
| `statusCode` | HTTP status returned to the caller. Default `200`. |
| `responseBody` | Body template. Supports `{placeholders}`. Default `{last_output}`. |
| `contentType` | `Content-Type` header. Default `application/json`. |
| `responseHeaders` | JSON object of extra response headers. Values can use `{placeholders}`. |
| `responseType` | `body` or `redirect`. Redirect responses set the `Location` header. |
| `redirectUrl` | URL used when `responseType=redirect`. Supports `{placeholders}`. |
| `bodyEncoding` | `text` or `base64`. Use `base64` for binary responses. |

The node writes `ctx.webhook_response` (`{statusCode, body, contentType, headers, bodyEncoding}`) and also sets `last_output` to the rendered body so any following node sees it.

## Example

Build a tiny JSON API:

```
Webhook (POST /orders)
  → Agent (validate + persist)
  → Respond to webhook
      statusCode: 201
      contentType: application/json
      responseBody: {"id": "{order_id}", "status": "created"}
```

Return a 4xx on a validation branch — branch *before* the single Respond node and set its fields from upstream:

```
If/else (input.amount <= 0)
  ├─ true  → Set state (status=400, error="invalid amount")
  └─ false → Agent (process) → Set state (status=200, ...)
            ↓
       Respond to webhook (statusCode: {state.status}, ...)
```

## Gotchas

- Only valid when an HTTP caller is waiting: a **Webhook** trigger or a **Start** entry (published API). With a **Schedule** or **Event listener** trigger the save is rejected (`400`) — there is no caller to answer.
- **One Respond node per workflow.** A second one fails validation at save.
- The body is rendered as a string. To return real JSON, set `contentType: application/json` and write the JSON inline — placeholders interpolated as strings won't add quotes for you.
- For binary responses, put a base64 string in `responseBody`, set `bodyEncoding: base64`, and choose the right `contentType`.
- Direct HTTP body streaming is not supported here. Long runs should use the webhook run poll/stream URLs returned by immediate mode.
- Once the response is flushed, the caller has it. Later nodes can run, but they cannot change the response.
- For long-running workflows, prefer `responseMode: immediate` on the Webhook node — the caller gets `200 OK` instantly and the workflow runs in the background.

---

*Source: https://agentbuilder.systalink.sn/docs/node-respond-webhook — human documentation.*
*Other language: [/docs-md/fr/node-respond-webhook.md](/docs-md/fr/node-respond-webhook.md).*
*Machine-readable index: [/llms.txt](/llms.txt).*
