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

# n8n

> The agent runs an n8n workflow during the call and passes the workflow's answer on to the caller. Plus: post-call events and starting calls from n8n.

n8n connects to BrosBots in three directions. This page covers the first,
which is its own integration in the catalogue, and points at the other two.

| Direction | What it does | Where |
| - | - | - |
| **Agent → n8n during the call** | The agent calls the workflow with call data and **hears what it answers** | this page |
| **BrosBots → n8n after an event** | A signed `POST` after a call, an SMS, a campaign, or on a low balance | [Webhooks](/en/integrations/webhooks) |
| **n8n → BrosBots** | n8n makes the agent call: a form lead, or through the API | [Lead callback](/en/integrations/leads/lead-webhook), [API trigger](/en/voice-agent/api-trigger) |

## How it differs from Zapier

The Zapier trigger sends data and that is the end of it: a Catch Hook does
not answer. An n8n workflow that ends with a **Respond to Webhook** node does,
and whatever it answers reaches the agent as the tool's result. So the agent
can not only push something into your systems but **ask them something**
while the caller is still on the line: an order's status in the shop, a free
slot in the booking system, a customer record in a database we have no
ready-made integration for.

A workflow without a Respond to Webhook node works too: n8n answers an empty
`200`, the agent gets "sent" and carries on.

## Connecting

<Steps>
  <Step title="The workflow in n8n">
    New workflow → **Webhook** node. Set **HTTP Method** to `POST`. If the
    workflow should answer the agent, set **Respond** to
    `Using 'Respond to Webhook' Node` and end the workflow with a
    **Respond to Webhook** node.

    Recommended: **Authentication** → `Header Auth`, a new credential with
    the header name `X-Brosbots-Secret` and any long value. You enter the same
    secret on our side.
  </Step>

  <Step title="Activate the workflow and copy the production URL">
    The **Active** toggle in the top right, then the **Production URL** tab in
    the Webhook node. The address has `/webhook/` in its path.

    <Warning>
      The address from the **Test URL** tab (path `/webhook-test/`) only works
      while **Listen for test event** is pressed in the editor. Connected to an
      agent, it works once, at your desk, and never again. The connection test
      warns when the pasted address is the test one.
    </Warning>
  </Step>

  <Step title="The connection in BrosBots">
    **Integrations** → **n8n**. Paste the production URL and the secret, if
    you set one. Saving delivers a test message, so the workflow runs once
    with `"event": "test"` in the body.
  </Step>

  <Step title="Switch the tool on in the agent">
    Agent editor → **Integrations** → **n8n workflow**. Pick the connection
    and fill in **When to use it, and what to say** and **Phrases that should
    trigger it**. Without those fields the agent has the tool but no idea what
    it is for - and usually leaves it alone. Details in [Slack, email, Zapier
    and the calendar during the
    call](/en/integrations/overview#slack-email-zapier-and-the-calendar-during-the-call).
  </Step>
</Steps>

The same toggle is in the new-agent wizard (**What your agent can do** →
**n8n workflow**): the address and secret entered there create the
connection on save.

<Note>
  The n8n integration is available from the **Start** plan, like Zapier and the
  webhooks.
</Note>

## What reaches the workflow

The agent sends a `POST` with JSON. It chooses `event` and `data` itself,
following what you wrote in **When to use it, and what to say**; the other
two fields are added by us, so the agent cannot invent them.

```json theme={null}
{
  "event": "order_status",
  "data": "order number 10482, the customer asks about the delivery date",
  "caller_phone": "+48600100200",
  "workflow_run_id": "3f1c2a7e-...."
}
```

| Field | Where it comes from |
| - | - |
| `event` | a short event name from the agent, e.g. `lead_qualified`, `order_status`, `appointment_booked` |
| `data` | what the agent collected during the call, or what it is asking about - free text |
| `caller_phone` | the caller's number (empty on a widget call) |
| `workflow_run_id` | the call id; the same one that arrives later in `call.completed` and fetches the transcript through the API |

With the `X-Brosbots-Secret` header when the connection has a secret.

## What the workflow can answer

The response body reaches the agent in the `result` field. The most
convenient answer is one sentence the agent should pass on:

```json theme={null}
{ "message": "Order 10482 was shipped yesterday, delivery tomorrow by 2 pm." }
```

Supported shapes:

| Response | What the agent gets |
| - | - |
| `{"message": "…"}` (also `result`, `answer`, `text`) | the text alone |
| plain text | the text as is |
| any other JSON | the JSON whole, up to 2000 characters - the agent reads it itself |
| an empty response | "sent", with no result |

The agent waits for the answer for up to **15 seconds**. The call is live, so
if the workflow does something slow, answer first and do the rest after the
response (in n8n: Respond to Webhook early in the chain, the heavy nodes
after it).

A `4xx`/`5xx` code is a tool error: the agent gets "n8n failed (code)" and
tells the caller it could not check. A `404` on the test address is named for
what it is: nobody is listening.

## A ready-made workflow to import

The smallest workflow: Webhook → Respond to Webhook. It answers with a
confirmation that repeats what it received, so you can hear in a call that
the path works. In n8n: **…** (workflow menu) → **Import from File**, or paste
the JSON through **Import from URL** / the clipboard.

```json theme={null}
{
  "name": "BrosBots - answer for the agent",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "brosbots-agent",
        "responseMode": "responseNode",
        "options": {}
      },
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"message\": \"Received event \" + $json.body.event + \": \" + $json.body.data } }}",
        "options": {}
      },
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [300, 0]
    }
  ],
  "connections": {
    "Webhook": { "main": [[{ "node": "Respond to Webhook", "type": "main", "index": 0 }]] }
  }
}
```

Put what should really happen between those two nodes: a shop query,
HubSpot, a spreadsheet, your own API. The agent's data is under
`$json.body.event` and `$json.body.data`.

## Post-call events in n8n

That is a separate integration, **Post-call webhook** in the catalogue, and a
separate workflow: a **Webhook** node with the `POST` method, its production
URL pasted into the webhook wizard. `call.completed` arrives with the
transcript, summary and outcome, and on request SMS, campaign and
`balance.low` events too; the format and the list of events are in
[Webhooks](/en/integrations/webhooks).

The `X-Brosbots-Signature` is usually not checked in n8n, because the address
is secret in itself. If you want to: switch on **Raw Body** in the Webhook
node, compute HMAC-SHA256 of the raw body with a **Crypto** node (Action
`Hmac`, Type `SHA256`, Encoding `Hex`, Secret = your `whsec_…` key) and
compare it with the header after stripping `sha256=`.

## Troubleshooting

| Symptom | Cause | What to do |
| - | - | - |
| Connection test: "test address" | a `/webhook-test/` URL was pasted | activate the workflow, paste the **Production URL** |
| Test: n8n returned `403` | Header Auth on the node, a different or empty secret on the connection | enter the same secret on both sides; the header name is `X-Brosbots-Secret` |
| Test: n8n returned `404` on the production URL | the workflow is inactive, or its path changed | the **Active** toggle, copy the address again |
| The agent says it could not check | the workflow returned an error or did not answer within 15 s | **Executions** in n8n shows which node failed; move Respond to Webhook ahead of the slow nodes |
| The agent never uses the tool | **When to use it, and what to say** is empty | describe when to call the workflow and what to pass |
| The agent reads out raw JSON | the workflow answers with a whole record | answer with `{"message": "…"}` and a finished sentence |

Every call shows up in n8n under **Executions**, with the body the agent
sent.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.