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

# Integrate Any System with Custom Functions

> Connect your agent to any external API or internal system using custom function calls.

## Overview

Custom functions let your agent call any external API via HTTP request — enabling integrations with your CRM, database, booking system, or any other service.

***

## Setup

<Steps>
  <Step title="Add the function">
    In your agent's Functions section, click **Add Function** and select **Custom Function**.
  </Step>

  <Step title="Name the function">
    Use underscores to separate words. Example: `check_order_status`, `create_lead`.

    <Frame>
      <img src="https://mintcdn.com/uponai/7QzWw_-VPReC-RSK/images/screenshots/image12.png?fit=max&auto=format&n=7QzWw_-VPReC-RSK&q=85&s=1224966ee3bd944c48660231ad94177a" alt="Custom Function form showing Name and Description fields" width="942" height="372" data-path="images/screenshots/image12.png" />
    </Frame>
  </Step>

  <Step title="Select HTTP method and set the endpoint URL">
    Choose from: `GET`, `POST`, `PATCH`, `PUT`, or `DELETE`. Enter the full URL of your API endpoint.

    <Frame>
      <img src="https://mintcdn.com/uponai/7QzWw_-VPReC-RSK/images/screenshots/image13.png?fit=max&auto=format&n=7QzWw_-VPReC-RSK&q=85&s=4c0f67e657c064ab596360e88001ac05" alt="Custom Function API endpoint configuration showing POST method, URL, timeout, and headers" width="935" height="519" data-path="images/screenshots/image13.png" />
    </Frame>
  </Step>

  <Step title="Configure headers and query parameters">
    Add any required authentication headers, API keys, or query params.
  </Step>

  <Step title="Define parameters">
    For `POST`, `PATCH`, and `PUT` requests, define your request body using JSON schema format.

    Enable **Payload: args only** to send only the function arguments as the JSON body, without an outer wrapper.
  </Step>

  <Step title="Handle the response">
    Map API response values to dynamic variables for use later in the conversation. Response data is capped at **15,000 characters**.

    Configure speech behavior during and after execution:

    * **Speak During Execution**: Agent says something while waiting (e.g. "Let me check that for you.")
    * **Speak After Execution**: Agent discusses the result with the caller

    <Frame>
      <img src="https://mintcdn.com/uponai/7QzWw_-VPReC-RSK/images/screenshots/image14.png?fit=max&auto=format&n=7QzWw_-VPReC-RSK&q=85&s=9575a47d55cffc1f8c61b2d84d212a04" alt="Response Variables mapping and Speak During/After Execution settings" width="959" height="547" data-path="images/screenshots/image14.png" />
    </Frame>
  </Step>
</Steps>

***

## Security

Every request includes an `X-Retell-Signature` header signed with your secret key. Verify this on your server to confirm requests are coming from UponAI.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const { Retell } = require('retell-sdk');
  const client = new Retell({ apiKey: 'YOUR_API_KEY' });

  app.post('/your-endpoint', (req, res) => {
    const valid = client.verify(
      JSON.stringify(req.body),
      req.headers['x-retell-signature']
    );
    if (!valid) return res.status(401).send('Unauthorized');
    // handle request
  });
  ```

  ```python Python theme={null}
  from retell import Retell

  client = Retell(api_key="YOUR_API_KEY")

  @app.route('/your-endpoint', methods=['POST'])
  def handle():
      valid = client.verify(
          request.get_data(as_text=True),
          request.headers.get('X-Retell-Signature')
      )
      if not valid:
          return 'Unauthorized', 401
      # handle request
  ```
</CodeGroup>

***

## Constraints

| Setting              | Value                |
| -------------------- | -------------------- |
| Timeout              | 2 minutes (default)  |
| Retries              | Up to 2 attempts     |
| Response cap         | 15,000 characters    |
| Function name format | Underscore-separated |
