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

# Pre-call webhooks for custom functions

> Fire a fire-and-forget webhook before a Bolna custom function runs its main API call, with a JSON body built from the tool arguments.

A custom function can fire a **pre-call webhook** — a notification sent to a URL of your choice *before* the tool's main API call runs. A common use case is a tool that transfers the call, where your system needs to receive the transfer reason *before* the transfer happens.

<Info>
  The pre-call webhook is **fire-and-forget**. A slow or failing webhook endpoint never blocks or fails the function call itself.
</Info>

<Note>
  The built-in [Transfer Call](/docs/tool-calling/transfer-calls#pre-call-webhook) tool supports the same pre-call webhook fields, fired *before* the transfer happens.
</Note>

## How it works

<Steps>
  <Step title="LLM decides to call the tool">
    The LLM produces the arguments for your custom function as usual.
  </Step>

  <Step title="Bolna fires the pre-call webhook">
    If the tool has a `pre_call_webhook_param` configured, Bolna first POSTs the pre-call webhook to the resolved URL.
  </Step>

  <Step title="The main API call runs">
    The tool's main function call then executes exactly as it normally would.
  </Step>
</Steps>

## Configuring the webhook body

`pre_call_webhook_param` is a JSON template that is completely independent from the tool's main `param`. You can reference any argument the LLM produced for the tool using the same `%(field)s` [substitution syntax](/docs/tool-calling/custom-function-schema#5-format-specifiers) used by `param`. Static values are passed through as-is.

```json theme={"system"}
{
  "name": "transfer_support",
  "description": "Transfers the call to a support agent when the caller asks for a human or has an issue the agent cannot resolve.",
  "parameters": {
    "type": "object",
    "properties": {
      "reason": {
        "type": "string",
        "description": "Why the caller wants a transfer"
      }
    },
    "required": ["reason"]
  },
  "key": "custom_task",
  "value": {
    "method": "POST",
    "url": "https://your-api.com/transfer",
    "param": {
      "reason": "%(reason)s"
    },
    "pre_call_webhook_url": "https://your-api.com/pre-transfer-hook",
    "pre_call_webhook_param": {
      "transfer_reason": "%(reason)s",
      "channel": "voice"
    }
  }
}
```

In the example above, `%(reason)s` is replaced with the LLM's argument for this tool call, while `"channel": "voice"` is a static value passed through unchanged.

## What your endpoint receives

The webhook body is the **same execution record** you receive on the [post-call execution webhook](/docs/post-call/polling-call-status-webhooks) (execution id, agent id, telephony details, status, etc.), merged with the fields from your `pre_call_webhook_param`:

```json theme={"system"}
{
  "id": "<execution_id>",
  "agent_id": "<agent_id>",
  "status": "in-progress",
  "telephony_data": { "...": "..." },
  "...": "...",

  "transfer_reason": "customer asked for billing",
  "channel": "voice"
}
```

<Note>
  Because the call is still in progress when the pre-call webhook fires, fields that are only finalized at call end (transcript, cost, summary) won't be complete yet.
</Note>

## URL resolution rules

| `pre_call_webhook_param` | `pre_call_webhook_url` | Result |
| - | - | - |
| Set | Set | Webhook sent to the tool's `pre_call_webhook_url`. |
| Set | Not set | Webhook sent to the **agent-level Webhook URL** (the same URL used for post-call execution webhooks). |
| Not set | Set or not set | **No pre-call webhook fires.** |

<Warning>
  **`pre_call_webhook_param` is the master switch.** If it is not set, no pre-call webhook fires — even if `pre_call_webhook_url` is configured. The agent's normal post-call webhook is unaffected.
</Warning>

<Warning>
  **Agent-level URL fallback:** when `pre_call_webhook_param` is set without a `pre_call_webhook_url`, the pre-call webhook is sent to your agent's configured [Webhook URL](/docs/post-call/polling-call-status-webhooks). If you already use that endpoint for post-call execution webhooks, it will now also receive pre-call webhooks. Distinguish them by the in-progress `status` and the extra fields from your `pre_call_webhook_param`.
</Warning>

## UI configuration

In the agent dashboard, the custom tool configuration (on the [Tools Tab](/docs/agent-setup/tools-tab)) has two optional inputs that map to these fields:

* **Pre-call webhook URL** — the endpoint to notify (`pre_call_webhook_url`).
* **Pre-call webhook parameters** — the JSON body template with `%(field)s` substitution (`pre_call_webhook_param`).

Both save with the tool and round-trip on edit.


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